home *** CD-ROM | disk | FTP | other *** search
/ Aminet 48 / Aminet 48 (2002)(GTI - Schatztruhe)[!][Apr 2002].iso / Aminet / text / edit / vim60src.lha / Vim / vim60 / src / normal.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-09-26  |  184.2 KB  |  7,882 lines

  1. /* vi:set ts=8 sts=4 sw=4:
  2.  *
  3.  * VIM - Vi IMproved    by Bram Moolenaar
  4.  *
  5.  * Do ":help uganda"  in Vim to read copying and usage conditions.
  6.  * Do ":help credits" in Vim to see a list of people who contributed.
  7.  * See README.txt for an overview of the Vim source code.
  8.  */
  9. /*
  10.  * normal.c:    Contains the main routine for processing characters in command
  11.  *        mode.  Communicates closely with the code in ops.c to handle
  12.  *        the operators.
  13.  */
  14.  
  15. #include "vim.h"
  16.  
  17. #ifdef FEAT_VISUAL
  18. /*
  19.  * The Visual area is remembered for reselection.
  20.  */
  21. static int    resel_VIsual_mode = NUL;    /* 'v', 'V', or Ctrl-V */
  22. static linenr_T    resel_VIsual_line_count;    /* number of lines */
  23. static colnr_T    resel_VIsual_col;        /* nr of cols or end col */
  24.  
  25. static int    restart_VIsual_select = 0;
  26. #endif
  27.  
  28. static int
  29. # ifdef __BORLANDC__
  30.     _RTLENTRYF
  31. # endif
  32.         nv_compare __ARGS((const void *s1, const void *s2));
  33. static int    find_command __ARGS((int cmdchar));
  34. static void    op_colon __ARGS((oparg_T *oap));
  35. #if defined(FEAT_MOUSE) && defined(FEAT_VISUAL)
  36. static void    find_start_of_word __ARGS((pos_T *));
  37. static void    find_end_of_word __ARGS((pos_T *));
  38. static int    get_mouse_class __ARGS((char_u *p));
  39. #endif
  40. static void    prep_redo_cmd __ARGS((cmdarg_T *cap));
  41. static void    prep_redo __ARGS((int regname, long, int, int, int, int, int));
  42. static int    checkclearop __ARGS((oparg_T *oap));
  43. static int    checkclearopq __ARGS((oparg_T *oap));
  44. static void    clearop __ARGS((oparg_T *oap));
  45. static void    clearopbeep __ARGS((oparg_T *oap));
  46. #ifdef FEAT_VISUAL
  47. static void    unshift_special __ARGS((cmdarg_T *cap));
  48. #endif
  49. #ifdef FEAT_CMDL_INFO
  50. static void    del_from_showcmd __ARGS((int));
  51. #endif
  52.  
  53. /*
  54.  * nv_*(): functions called to handle Normal and Visual mode commands.
  55.  * n_*(): functions called to handle Normal mode commands.
  56.  * v_*(): functions called to handle Visual mode commands.
  57.  */
  58. static void    nv_ignore __ARGS((cmdarg_T *cap));
  59. static void    nv_error __ARGS((cmdarg_T *cap));
  60. static void    nv_help __ARGS((cmdarg_T *cap));
  61. static void    nv_addsub __ARGS((cmdarg_T *cap));
  62. static void    nv_page __ARGS((cmdarg_T *cap));
  63. static void    nv_gd __ARGS((oparg_T *oap, int nchar));
  64. static int    nv_screengo __ARGS((oparg_T *oap, int dir, long dist));
  65. #ifdef FEAT_MOUSE
  66. static void    nv_mousescroll __ARGS((cmdarg_T *cap));
  67. static void    nv_mouse __ARGS((cmdarg_T *cap));
  68. #endif
  69. static void    nv_scroll_line __ARGS((cmdarg_T *cap));
  70. static void    nv_zet __ARGS((cmdarg_T *cap));
  71. #ifdef FEAT_GUI
  72. static void    nv_ver_scrollbar __ARGS((cmdarg_T *cap));
  73. static void    nv_hor_scrollbar __ARGS((cmdarg_T *cap));
  74. #endif
  75. static void    nv_exmode __ARGS((cmdarg_T *cap));
  76. static void    nv_colon __ARGS((cmdarg_T *cap));
  77. static void    nv_ctrlg __ARGS((cmdarg_T *cap));
  78. static void    nv_ctrlh __ARGS((cmdarg_T *cap));
  79. static void    nv_clear __ARGS((cmdarg_T *cap));
  80. static void    nv_ctrlo __ARGS((cmdarg_T *cap));
  81. static void    nv_hat __ARGS((cmdarg_T *cap));
  82. static void    nv_Zet __ARGS((cmdarg_T *cap));
  83. static void    nv_ident __ARGS((cmdarg_T *cap));
  84. #ifdef FEAT_VISUAL
  85. static int    get_visual_text __ARGS((cmdarg_T *cap, char_u **pp, int *lenp));
  86. #endif
  87. static void    nv_tagpop __ARGS((cmdarg_T *cap));
  88. static void    nv_scroll __ARGS((cmdarg_T *cap));
  89. static void    nv_right __ARGS((cmdarg_T *cap));
  90. static void    nv_left __ARGS((cmdarg_T *cap));
  91. static void    nv_up __ARGS((cmdarg_T *cap));
  92. static void    nv_down __ARGS((cmdarg_T *cap));
  93. #ifdef FEAT_SEARCHPATH
  94. static void    nv_gotofile __ARGS((cmdarg_T *cap));
  95. #endif
  96. static void    nv_end __ARGS((cmdarg_T *cap));
  97. static void    nv_dollar __ARGS((cmdarg_T *cap));
  98. static void    nv_search __ARGS((cmdarg_T *cap));
  99. static void    nv_next __ARGS((cmdarg_T *cap));
  100. static void    normal_search __ARGS((cmdarg_T *cap, int dir, char_u *pat, int opt));
  101. static void    nv_csearch __ARGS((cmdarg_T *cap));
  102. static void    nv_brackets __ARGS((cmdarg_T *cap));
  103. static void    nv_percent __ARGS((cmdarg_T *cap));
  104. static void    nv_brace __ARGS((cmdarg_T *cap));
  105. static void    nv_mark __ARGS((cmdarg_T *cap));
  106. static void    nv_findpar __ARGS((cmdarg_T *cap));
  107. static void    nv_undo __ARGS((cmdarg_T *cap));
  108. static void    nv_kundo __ARGS((cmdarg_T *cap));
  109. static void    nv_Replace __ARGS((cmdarg_T *cap));
  110. #ifdef FEAT_VREPLACE
  111. static void    nv_vreplace __ARGS((cmdarg_T *cap));
  112. #endif
  113. #ifdef FEAT_VISUAL
  114. static void    v_swap_corners __ARGS((int cmdchar));
  115. #endif
  116. static void    nv_replace __ARGS((cmdarg_T *cap));
  117. static void    n_swapchar __ARGS((cmdarg_T *cap));
  118. static void    nv_cursormark __ARGS((cmdarg_T *cap, int flag, pos_T *pos));
  119. #ifdef FEAT_VISUAL
  120. static void    v_visop __ARGS((cmdarg_T *cap));
  121. #endif
  122. static void    nv_subst __ARGS((cmdarg_T *cap));
  123. static void    nv_abbrev __ARGS((cmdarg_T *cap));
  124. static void    nv_optrans __ARGS((cmdarg_T *cap));
  125. static void    nv_gomark __ARGS((cmdarg_T *cap));
  126. static void    nv_pcmark __ARGS((cmdarg_T *cap));
  127. static void    nv_regname __ARGS((cmdarg_T *cap));
  128. #ifdef FEAT_VISUAL
  129. static void    nv_visual __ARGS((cmdarg_T *cap));
  130. static void    n_start_visual_mode __ARGS((int c));
  131. #endif
  132. static void    nv_window __ARGS((cmdarg_T *cap));
  133. static void    nv_suspend __ARGS((cmdarg_T *cap));
  134. static void    nv_g_cmd __ARGS((cmdarg_T *cap));
  135. static void    n_opencmd __ARGS((cmdarg_T *cap));
  136. static void    nv_dot __ARGS((cmdarg_T *cap));
  137. static void    nv_redo __ARGS((cmdarg_T *cap));
  138. static void    nv_Undo __ARGS((cmdarg_T *cap));
  139. static void    nv_tilde __ARGS((cmdarg_T *cap));
  140. static void    nv_operator __ARGS((cmdarg_T *cap));
  141. static void    nv_lineop __ARGS((cmdarg_T *cap));
  142. static void    nv_home __ARGS((cmdarg_T *cap));
  143. static void    nv_pipe __ARGS((cmdarg_T *cap));
  144. static void    nv_bck_word __ARGS((cmdarg_T *cap));
  145. static void    nv_wordcmd __ARGS((cmdarg_T *cap));
  146. static void    nv_beginline __ARGS((cmdarg_T *cap));
  147. #ifdef FEAT_VISUAL
  148. static void    adjust_for_sel __ARGS((cmdarg_T *cap));
  149. static int    unadjust_for_sel __ARGS((void));
  150. static void    nv_select __ARGS((cmdarg_T *cap));
  151. #endif
  152. static void    nv_goto __ARGS((cmdarg_T *cap));
  153. static void    nv_normal __ARGS((cmdarg_T *cap));
  154. static void    nv_esc __ARGS((cmdarg_T *oap));
  155. static void    nv_edit __ARGS((cmdarg_T *cap));
  156. #ifdef FEAT_TEXTOBJ
  157. static void    nv_object __ARGS((cmdarg_T *cap));
  158. #endif
  159. static void    nv_record __ARGS((cmdarg_T *cap));
  160. static void    nv_at __ARGS((cmdarg_T *cap));
  161. static void    nv_halfpage __ARGS((cmdarg_T *cap));
  162. static void    nv_join __ARGS((cmdarg_T *cap));
  163. static void    nv_put __ARGS((cmdarg_T *cap));
  164. static void    nv_open __ARGS((cmdarg_T *cap));
  165. #ifdef FEAT_SNIFF
  166. static void    nv_sniff __ARGS((cmdarg_T *cap));
  167. #endif
  168.  
  169. /*
  170.  * Function to be called for a Normal or Visual mode command.
  171.  * The argument is a cmdarg_T.
  172.  */
  173. typedef void (*nv_func_T) __ARGS((cmdarg_T *cap));
  174.  
  175. /* Values for cmd_flags. */
  176. #define NV_NCH        0x01      /* may need to get a second char */
  177. #define NV_NCH_NOP  (0x02|NV_NCH) /* get second char when no operator pending */
  178. #define NV_NCH_ALW  (0x04|NV_NCH) /* always get a second char */
  179. #define NV_LANG        0x08    /* second char needs language adjustment */
  180.  
  181. #define NV_SS        0x10    /* may start selection */
  182. #define NV_SSS        0x20    /* may start selection with shift modifier */
  183. #define NV_STS        0x40    /* may stop selection without shift modif. */
  184. #define NV_RL        0x80    /* 'rightleft' modifies command */
  185. #define NV_KEEPREG  0x100    /* don't clear regname */
  186. #define NV_NCW        0x200    /* not allowed in command-line window */
  187.  
  188. /*
  189.  * Generally speaking, every Normal mode command should either clear any
  190.  * pending operator (with *clearop*()), or set the motion type variable
  191.  * oap->motion_type.
  192.  *
  193.  * When a cursor motion command is made, it is marked as being a character or
  194.  * line oriented motion.  Then, if an operator is in effect, the operation
  195.  * becomes character or line oriented accordingly.
  196.  */
  197.  
  198. /*
  199.  * This table contains one entry for every Normal or Visual mode command.
  200.  * The order doesn't matter, init_normal_cmds() will create a sorted index.
  201.  * It is faster when all keys from zero to '~' are present.
  202.  */
  203. static const struct nv_cmd
  204. {
  205.     int        cmd_char;    /* (first) command character */
  206.     nv_func_T   cmd_func;    /* function for this command */
  207.     short_u    cmd_flags;    /* NV_ flags */
  208.     short    cmd_arg;    /* value for ca.arg */
  209. } nv_cmds[] =
  210. {
  211.     {NUL,    nv_error,    0,            0},
  212.     {Ctrl_A,    nv_addsub,    0,            0},
  213.     {Ctrl_B,    nv_page,    NV_STS,            BACKWARD},
  214.     {Ctrl_C,    nv_esc,        0,            TRUE},
  215.     {Ctrl_D,    nv_halfpage,    0,            0},
  216.     {Ctrl_E,    nv_scroll_line,    0,            TRUE},
  217.     {Ctrl_F,    nv_page,    NV_STS,            FORWARD},
  218.     {Ctrl_G,    nv_ctrlg,    0,            0},
  219.     {Ctrl_H,    nv_ctrlh,    0,            0},
  220.     {Ctrl_I,    nv_pcmark,    0,            0},
  221.     {NL,    nv_down,    0,            FALSE},
  222.     {Ctrl_K,    nv_error,    0,            0},
  223.     {Ctrl_L,    nv_clear,    0,            0},
  224.     {CR,    nv_down,    0,            TRUE},
  225.     {Ctrl_N,    nv_down,    NV_STS,            FALSE},
  226.     {Ctrl_O,    nv_ctrlo,    0,            0},
  227.     {Ctrl_P,    nv_up,        NV_STS,            FALSE},
  228.     {Ctrl_Q,    nv_ignore,    0,            0},
  229.     {Ctrl_R,    nv_redo,    0,            0},
  230.     {Ctrl_S,    nv_ignore,    0,            0},
  231.     {Ctrl_T,    nv_tagpop,    NV_NCW,            0},
  232.     {Ctrl_U,    nv_halfpage,    0,            0},
  233. #ifdef FEAT_VISUAL
  234.     {Ctrl_V,    nv_visual,    0,            FALSE},
  235.     {'V',    nv_visual,    0,            FALSE},
  236.     {'v',    nv_visual,    0,            FALSE},
  237. #else
  238.     {Ctrl_V,    nv_error,    0,            0},
  239.     {'V',    nv_error,    0,            0},
  240.     {'v',    nv_error,    0,            0},
  241. #endif
  242.     {Ctrl_W,    nv_window,    0,            0},
  243.     {Ctrl_X,    nv_addsub,    0,            0},
  244.     {Ctrl_Y,    nv_scroll_line,    0,            FALSE},
  245.     {Ctrl_Z,    nv_suspend,    0,            0},
  246.     {ESC,    nv_esc,        0,            FALSE},
  247.     {Ctrl_BSL,    nv_normal,    0,            0},
  248.     {Ctrl_RSB,    nv_ident,    NV_NCW,            0},
  249.     {Ctrl_HAT,    nv_hat,        NV_NCW,            0},
  250.     {Ctrl__,    nv_error,    0,            0},
  251.     {' ',    nv_right,    0,            0},
  252.     {'!',    nv_operator,    0,            0},
  253.     {'"',    nv_regname,    NV_NCH_NOP|NV_KEEPREG,    0},
  254.     {'#',    nv_ident,    0,            0},
  255.     {'$',    nv_dollar,    0,            0},
  256.     {'%',    nv_percent,    0,            0},
  257.     {'&',    nv_optrans,    0,            0},
  258.     {'\'',    nv_gomark,    NV_NCH_ALW,        TRUE},
  259.     {'(',    nv_brace,    0,            BACKWARD},
  260.     {')',    nv_brace,    0,            FORWARD},
  261.     {'*',    nv_ident,    0,            0},
  262.     {'+',    nv_down,    0,            TRUE},
  263.     {',',    nv_csearch,    0,            TRUE},
  264.     {'-',    nv_up,        0,            TRUE},
  265.     {'.',    nv_dot,        NV_KEEPREG,        0},
  266.     {'/',    nv_search,    0,            FALSE},
  267.     {'0',    nv_beginline,    0,            0},
  268.     {'1',    nv_ignore,    0,            0},
  269.     {'2',    nv_ignore,    0,            0},
  270.     {'3',    nv_ignore,    0,            0},
  271.     {'4',    nv_ignore,    0,            0},
  272.     {'5',    nv_ignore,    0,            0},
  273.     {'6',    nv_ignore,    0,            0},
  274.     {'7',    nv_ignore,    0,            0},
  275.     {'8',    nv_ignore,    0,            0},
  276.     {'9',    nv_ignore,    0,            0},
  277.     {':',    nv_colon,    0,            0},
  278.     {';',    nv_csearch,    0,            FALSE},
  279.     {'<',    nv_operator,    NV_RL,            0},
  280.     {'=',    nv_operator,    0,            0},
  281.     {'>',    nv_operator,    NV_RL,            0},
  282.     {'?',    nv_search,    0,            FALSE},
  283.     {'@',    nv_at,        NV_NCH_NOP,        FALSE},
  284.     {'A',    nv_edit,    0,            0},
  285.     {'B',    nv_bck_word,    0,            1},
  286.     {'C',    nv_abbrev,    NV_KEEPREG,        0},
  287.     {'D',    nv_abbrev,    NV_KEEPREG,        0},
  288.     {'E',    nv_wordcmd,    0,            TRUE},
  289.     {'F',    nv_csearch,    NV_NCH_ALW|NV_LANG,    BACKWARD},
  290.     {'G',    nv_goto,    0,            TRUE},
  291.     {'H',    nv_scroll,    0,            0},
  292.     {'I',    nv_edit,    0,            0},
  293.     {'J',    nv_join,    0,            0},
  294.     {'K',    nv_ident,    0,            0},
  295.     {'L',    nv_scroll,    0,            0},
  296.     {'M',    nv_scroll,    0,            0},
  297.     {'N',    nv_next,    0,            SEARCH_REV},
  298.     {'O',    nv_open,    0,            0},
  299.     {'P',    nv_put,        0,            0},
  300.     {'Q',    nv_exmode,    NV_NCW,            0},
  301.     {'R',    nv_Replace,    0,            FALSE},
  302.     {'S',    nv_subst,    NV_KEEPREG,        0},
  303.     {'T',    nv_csearch,    NV_NCH_ALW|NV_LANG,    BACKWARD},
  304.     {'U',    nv_Undo,    0,            0},
  305.     {'W',    nv_wordcmd,    0,            TRUE},
  306.     {'X',    nv_abbrev,    NV_KEEPREG,        0},
  307.     {'Y',    nv_abbrev,    NV_KEEPREG,        0},
  308.     {'Z',    nv_Zet,        NV_NCH_NOP|NV_NCW,    0},
  309.     {'[',    nv_brackets,    NV_NCH_ALW,        BACKWARD},
  310.     {'\\',    nv_error,    0,            0},
  311.     {']',    nv_brackets,    NV_NCH_ALW,        FORWARD},
  312.     {'^',    nv_beginline,    0,            BL_WHITE | BL_FIX},
  313.     {'_',    nv_lineop,    0,            0},
  314.     {'`',    nv_gomark,    NV_NCH_ALW,        FALSE},
  315.     {'a',    nv_edit,    NV_NCH,            0},
  316.     {'b',    nv_bck_word,    0,            0},
  317.     {'c',    nv_operator,    0,            0},
  318.     {'d',    nv_operator,    0,            0},
  319.     {'e',    nv_wordcmd,    0,            FALSE},
  320.     {'f',    nv_csearch,    NV_NCH_ALW|NV_LANG,    FORWARD},
  321.     {'g',    nv_g_cmd,    NV_NCH_ALW,        FALSE},
  322.     {'h',    nv_left,    NV_RL,            0},
  323.     {'i',    nv_edit,    NV_NCH,            0},
  324.     {'j',    nv_down,    0,            FALSE},
  325.     {'k',    nv_up,        0,            FALSE},
  326.     {'l',    nv_right,    NV_RL,            0},
  327.     {'m',    nv_mark,    NV_NCH_NOP,        0},
  328.     {'n',    nv_next,    0,            0},
  329.     {'o',    nv_open,    0,            0},
  330.     {'p',    nv_put,        0,            0},
  331.     {'q',    nv_record,    NV_NCH,            0},
  332.     {'r',    nv_replace,    NV_NCH_NOP|NV_LANG,    0},
  333.     {'s',    nv_subst,    NV_KEEPREG,        0},
  334.     {'t',    nv_csearch,    NV_NCH_ALW|NV_LANG,    FORWARD},
  335.     {'u',    nv_undo,    0,            0},
  336.     {'w',    nv_wordcmd,    0,            FALSE},
  337.     {'x',    nv_abbrev,    NV_KEEPREG,        0},
  338.     {'y',    nv_operator,    0,            0},
  339.     {'z',    nv_zet,        NV_NCH_NOP,        0},
  340.     {'{',    nv_findpar,    0,            BACKWARD},
  341.     {'|',    nv_pipe,    0,            0},
  342.     {'}',    nv_findpar,    0,            FORWARD},
  343.     {'~',    nv_tilde,    0,            0},
  344.  
  345.     /* pound sign */
  346.     {POUND,    nv_ident,    0,            0},
  347. #ifdef FEAT_MOUSE
  348.     {K_MOUSEUP, nv_mousescroll,    0,            TRUE},
  349.     {K_MOUSEDOWN, nv_mousescroll, 0,            FALSE},
  350.     {K_LEFTMOUSE, nv_mouse,    0,            0},
  351.     {K_LEFTMOUSE_NM, nv_mouse,    0,            0},
  352.     {K_LEFTDRAG, nv_mouse,    0,            0},
  353.     {K_LEFTRELEASE, nv_mouse,    0,            0},
  354.     {K_LEFTRELEASE_NM, nv_mouse, 0,            0},
  355.     {K_MIDDLEMOUSE, nv_mouse,    0,            0},
  356.     {K_MIDDLEDRAG, nv_mouse,    0,            0},
  357.     {K_MIDDLERELEASE, nv_mouse,    0,            0},
  358.     {K_RIGHTMOUSE, nv_mouse,    0,            0},
  359.     {K_RIGHTDRAG, nv_mouse,    0,            0},
  360.     {K_RIGHTRELEASE, nv_mouse,    0,            0},
  361. #endif
  362.     {K_IGNORE,    nv_ignore,    0,            0},
  363.     {K_INS,    nv_edit,    0,            0},
  364.     {K_KINS,    nv_edit,    0,            0},
  365.     {K_BS,    nv_ctrlh,    0,            0},
  366.     {K_UP,    nv_up,        NV_SSS|NV_STS,        FALSE},
  367.     {K_S_UP,    nv_page,    NV_SS,            BACKWARD},
  368.     {K_DOWN,    nv_down,    NV_SSS|NV_STS,        FALSE},
  369.     {K_S_DOWN,    nv_page,    NV_SS,            FORWARD},
  370.     {K_LEFT,    nv_left,    NV_SSS|NV_STS|NV_RL,    0},
  371.     {K_S_LEFT,    nv_bck_word,    NV_SS|NV_RL,        0},
  372.     {K_C_LEFT,    nv_bck_word,    NV_SSS|NV_RL|NV_STS,    1},
  373.     {K_RIGHT,    nv_right,    NV_SSS|NV_STS|NV_RL,    0},
  374.     {K_S_RIGHT,    nv_wordcmd,    NV_SS|NV_RL,        FALSE},
  375.     {K_C_RIGHT,    nv_wordcmd,    NV_SSS|NV_RL|NV_STS,    TRUE},
  376.     {K_PAGEUP,    nv_page,    NV_SSS|NV_STS,        BACKWARD},
  377.     {K_KPAGEUP,    nv_page,    NV_SSS|NV_STS,        BACKWARD},
  378.     {K_PAGEDOWN, nv_page,    NV_SSS|NV_STS,        FORWARD},
  379.     {K_KPAGEDOWN, nv_page,    NV_SSS|NV_STS,        FORWARD},
  380.     {K_END,    nv_end,        NV_SSS|NV_STS,        FALSE},
  381.     {K_KEND,    nv_end,        NV_SSS|NV_STS,        FALSE},
  382.     {K_XEND,    nv_end,        NV_SSS|NV_STS,        FALSE},
  383.     {K_S_END,    nv_end,        NV_SS,            FALSE},
  384.     {K_C_END,    nv_end,        NV_SSS|NV_STS,        TRUE},
  385.     {K_HOME,    nv_home,    NV_SSS|NV_STS,        0},
  386.     {K_KHOME,    nv_home,    NV_SSS|NV_STS,        0},
  387.     {K_XHOME,    nv_home,    NV_SSS|NV_STS,        0},
  388.     {K_S_HOME,    nv_home,    NV_SS,            0},
  389.     {K_C_HOME,    nv_goto,    NV_SSS|NV_STS,        FALSE},
  390.     {K_DEL,    nv_abbrev,    0,            0},
  391.     {K_KDEL,    nv_abbrev,    0,            0},
  392.     {K_UNDO,    nv_kundo,    0,            0},
  393.     {K_HELP,    nv_help,    NV_NCW,            0},
  394.     {K_F1,    nv_help,    NV_NCW,            0},
  395.     {K_XF1,    nv_help,    NV_NCW,            0},
  396. #ifdef FEAT_VISUAL
  397.     {K_SELECT,    nv_select,    0,            0},
  398. #endif
  399. #ifdef FEAT_GUI
  400.     {K_VER_SCROLLBAR, nv_ver_scrollbar, 0,        0},
  401.     {K_HOR_SCROLLBAR, nv_hor_scrollbar, 0,        0},
  402. #endif
  403. #ifdef FEAT_FKMAP
  404.     {K_F8,    farsi_fkey,    0,            0},
  405.     {K_F9,    farsi_fkey,    0,            0},
  406. #endif
  407. #ifdef FEAT_SNIFF
  408.     {K_SNIFF,    nv_sniff,    0,            0},
  409. #endif
  410. };
  411.  
  412. /* Number of commands in nv_cmds[]. */
  413. #define NV_CMDS_SIZE (sizeof(nv_cmds) / sizeof(struct nv_cmd))
  414.  
  415. /* Sorted index of commands in nv_cmds[]. */
  416. static short nv_cmd_idx[NV_CMDS_SIZE];
  417.  
  418. /* The highest index for which
  419.  * nv_cmds[idx].cmd_char == nv_cmd_idx[nv_cmds[idx].cmd_char] */
  420. static int nv_max_linear;
  421.  
  422. /*
  423.  * Compare functions for qsort() below, that checks the command character
  424.  * through the index in nv_cmd_idx[].
  425.  */
  426.     static int
  427. #ifdef __BORLANDC__
  428. _RTLENTRYF
  429. #endif
  430. nv_compare(s1, s2)
  431.     const void    *s1;
  432.     const void    *s2;
  433. {
  434.     int        c1, c2;
  435.  
  436.     /* The commands are sorted on absolute value. */
  437.     c1 = nv_cmds[*(const short *)s1].cmd_char;
  438.     c2 = nv_cmds[*(const short *)s2].cmd_char;
  439.     if (c1 < 0)
  440.     c1 = -c1;
  441.     if (c2 < 0)
  442.     c2 = -c2;
  443.     return c1 - c2;
  444. }
  445.  
  446. /*
  447.  * Initialize the nv_cmd_idx[] table.
  448.  */
  449.     void
  450. init_normal_cmds()
  451. {
  452.     int        i;
  453.  
  454.     /* Fill the index table with a one to one relation. */
  455.     for (i = 0; i < NV_CMDS_SIZE; ++i)
  456.     nv_cmd_idx[i] = i;
  457.  
  458.     /* Sort the commands by the command character.  */
  459.     qsort((void *)&nv_cmd_idx, (size_t)NV_CMDS_SIZE, sizeof(short), nv_compare);
  460.  
  461.     /* Find the first entry that can't be indexed by the command character. */
  462.     for (i = 0; i < NV_CMDS_SIZE; ++i)
  463.     if (i != nv_cmds[nv_cmd_idx[i]].cmd_char)
  464.         break;
  465.     nv_max_linear = i - 1;
  466. }
  467.  
  468. /*
  469.  * Search for a command in the commands table.
  470.  * Returns -1 for invalid command.
  471.  */
  472.     static int
  473. find_command(cmdchar)
  474.     int        cmdchar;
  475. {
  476.     int        i;
  477.     int        idx;
  478.     int        top, bot;
  479.     int        c;
  480.  
  481. #ifdef FEAT_MBYTE
  482.     /* A multi-byte character is never a command. */
  483.     if (cmdchar >= 0x100)
  484.     return -1;
  485. #endif
  486.  
  487.     /* We use the absolute value of the character.  Special keys have a
  488.      * negative value, but are sorted on their absolute value. */
  489.     if (cmdchar < 0)
  490.     cmdchar = -cmdchar;
  491.  
  492.     /* If the character is in the first part: The character is the index into
  493.      * nv_cmd_idx[]. */
  494.     if (cmdchar <= nv_max_linear)
  495.     return nv_cmd_idx[cmdchar];
  496.  
  497.     /* Perform a binary search. */
  498.     bot = nv_max_linear + 1;
  499.     top = NV_CMDS_SIZE - 1;
  500.     idx = -1;
  501.     while (bot <= top)
  502.     {
  503.     i = (top + bot) / 2;
  504.     c = nv_cmds[nv_cmd_idx[i]].cmd_char;
  505.     if (c < 0)
  506.         c = -c;
  507.     if (cmdchar == c)
  508.     {
  509.         idx = nv_cmd_idx[i];
  510.         break;
  511.     }
  512.     if (cmdchar > c)
  513.         bot = i + 1;
  514.     else
  515.         top = i - 1;
  516.     }
  517.     return idx;
  518. }
  519.  
  520. /*
  521.  * Execute a command in Normal mode.
  522.  */
  523. /*ARGSUSED*/
  524.     void
  525. normal_cmd(oap, toplevel)
  526.     oparg_T    *oap;
  527.     int        toplevel;        /* TRUE when called from main() */
  528. {
  529.     static long    opcount = 0;        /* ca.opcount saved here */
  530.     cmdarg_T    ca;            /* command arguments */
  531.     int        c;
  532.     int        ctrl_w = FALSE;        /* got CTRL-W command */
  533.     int        old_col = curwin->w_curswant;
  534. #ifdef FEAT_CMDL_INFO
  535.     int        need_flushbuf;        /* need to call out_flush() */
  536. #endif
  537. #ifdef FEAT_VISUAL
  538.     pos_T    old_pos;        /* cursor position before command */
  539.     int        mapped_len;
  540. #endif
  541.     static int    old_mapped_len = 0;
  542.     int        idx;
  543.  
  544.     vim_memset(&ca, 0, sizeof(ca));    /* also resets ca.retval */
  545.     ca.oap = oap;
  546.     ca.opcount = opcount;
  547.  
  548. #ifdef FEAT_SNIFF
  549.     want_sniff_request = sniff_connected;
  550. #endif
  551.  
  552.     /*
  553.      * If there is an operator pending, then the command we take this time
  554.      * will terminate it. Finish_op tells us to finish the operation before
  555.      * returning this time (unless the operation was cancelled).
  556.      */
  557. #ifdef CURSOR_SHAPE
  558.     c = finish_op;
  559. #endif
  560.     finish_op = (oap->op_type != OP_NOP);
  561. #ifdef CURSOR_SHAPE
  562.     if (finish_op != c)
  563.     {
  564.     ui_cursor_shape();        /* may show different cursor shape */
  565. # ifdef FEAT_MOUSESHAPE
  566.     update_mouseshape(-1);
  567. # endif
  568.     }
  569. #endif
  570.  
  571.     if (!finish_op && !oap->regname)
  572.     ca.opcount = 0;
  573.  
  574. #ifdef FEAT_VISUAL
  575.     mapped_len = typebuf_maplen();
  576. #endif
  577.  
  578.     State = NORMAL_BUSY;
  579. #ifdef USE_ON_FLY_SCROLL
  580.     dont_scroll = FALSE;    /* allow scrolling here */
  581. #endif
  582.  
  583.     /*
  584.      * Get the command character from the user.
  585.      */
  586.     c = safe_vgetc();
  587.  
  588. #ifdef FEAT_LANGMAP
  589.     LANGMAP_ADJUST(c, TRUE);
  590. #endif
  591.  
  592.     /*
  593.      * If a mapping was started in Visual or Select mode, remember the length
  594.      * of the mapping.  This is used below to not return to Insert mode for as
  595.      * long as the mapping is being executed.
  596.      */
  597.     if (restart_edit == 0)
  598.     old_mapped_len = 0;
  599.     else if (old_mapped_len
  600. #ifdef FEAT_VISUAL
  601.         || (VIsual_active && mapped_len == 0 && typebuf_maplen() > 0)
  602. #endif
  603.         )
  604.     old_mapped_len = typebuf_maplen();
  605.  
  606.     if (c == NUL)
  607.     c = K_ZERO;
  608.  
  609. #ifdef FEAT_VISUAL
  610.     /*
  611.      * In Select mode, typed text replaces the selection.
  612.      */
  613.     if (VIsual_active
  614.         && VIsual_select
  615.         && (vim_isprintc(c) || c == NL || c == CR || c == K_KENTER))
  616.     {
  617.     stuffcharReadbuff(c);
  618.     c = 'c';
  619.     }
  620. #endif
  621.  
  622. #ifdef FEAT_CMDL_INFO
  623.     need_flushbuf = add_to_showcmd(c);
  624. #endif
  625.  
  626. getcount:
  627. #ifdef FEAT_VISUAL
  628.     if (!(VIsual_active && VIsual_select))
  629. #endif
  630.     {
  631.     /*
  632.      * Handle a count before a command and compute ca.count0.
  633.      * Note that '0' is a command and not the start of a count, but it's
  634.      * part of a count after other digits.
  635.      */
  636.     while (    (c >= '1' && c <= '9')
  637.         || (ca.count0 != 0 && (c == K_DEL || c == K_KDEL || c == '0')))
  638.     {
  639.         if (c == K_DEL || c == K_KDEL)
  640.         {
  641.         ca.count0 /= 10;
  642. #ifdef FEAT_CMDL_INFO
  643.         del_from_showcmd(4);    /* delete the digit and ~@% */
  644. #endif
  645.         }
  646.         else
  647.         ca.count0 = ca.count0 * 10 + (c - '0');
  648.         if (ca.count0 < 0)        /* got too large! */
  649.         ca.count0 = 999999999L;
  650.         if (ctrl_w)
  651.         {
  652.         ++no_mapping;
  653.         ++allow_keys;        /* no mapping for nchar, but keys */
  654.         }
  655.         c = safe_vgetc();
  656. #ifdef FEAT_LANGMAP
  657.         LANGMAP_ADJUST(c, TRUE);
  658. #endif
  659.         if (ctrl_w)
  660.         {
  661.         --no_mapping;
  662.         --allow_keys;
  663.         }
  664. #ifdef FEAT_CMDL_INFO
  665.         need_flushbuf |= add_to_showcmd(c);
  666. #endif
  667.     }
  668.  
  669.     /*
  670.      * If we got CTRL-W there may be a/another count
  671.      */
  672.     if (c == Ctrl_W && !ctrl_w && oap->op_type == OP_NOP)
  673.     {
  674.         ctrl_w = TRUE;
  675.         ca.opcount = ca.count0;    /* remember first count */
  676.         ca.count0 = 0;
  677.         ++no_mapping;
  678.         ++allow_keys;        /* no mapping for nchar, but keys */
  679.         c = safe_vgetc();        /* get next character */
  680. #ifdef FEAT_LANGMAP
  681.         LANGMAP_ADJUST(c, TRUE);
  682. #endif
  683.         --no_mapping;
  684.         --allow_keys;
  685. #ifdef FEAT_CMDL_INFO
  686.         need_flushbuf |= add_to_showcmd(c);
  687. #endif
  688.         goto getcount;        /* jump back */
  689.     }
  690.     }
  691.  
  692.     /*
  693.      * If we're in the middle of an operator (including after entering a yank
  694.      * buffer with '"') AND we had a count before the operator, then that
  695.      * count overrides the current value of ca.count0.
  696.      * What this means effectively, is that commands like "3dw" get turned
  697.      * into "d3w" which makes things fall into place pretty neatly.
  698.      * If you give a count before AND after the operator, they are multiplied.
  699.      */
  700.     if (ca.opcount != 0)
  701.     {
  702.     if (ca.count0)
  703.         ca.count0 *= ca.opcount;
  704.     else
  705.         ca.count0 = ca.opcount;
  706.     }
  707.  
  708.     /*
  709.      * Always remember the count.  It will be set to zero (on the next call,
  710.      * above) when there is no pending operator.
  711.      * When called from main(), save the count for use by the "count" built-in
  712.      * variable.
  713.      */
  714.     ca.opcount = ca.count0;
  715.     ca.count1 = (ca.count0 == 0 ? 1 : ca.count0);
  716.  
  717. #ifdef FEAT_EVAL
  718.     /*
  719.      * Only set v:count when called from main() and not a stuffed command.
  720.      */
  721.     if (toplevel && stuff_empty())
  722.     set_vcount(ca.count0, ca.count1);
  723. #endif
  724.  
  725.     /*
  726.      * Find the command character in the table of commands.
  727.      * For CTRL-W we already got nchar when looking for a count.
  728.      */
  729.     if (ctrl_w)
  730.     {
  731.     ca.nchar = c;
  732.     ca.cmdchar = Ctrl_W;
  733.     }
  734.     else
  735.     ca.cmdchar = c;
  736.     idx = find_command(ca.cmdchar);
  737.     if (idx < 0)
  738.     {
  739.     /* Not a known command: beep. */
  740.     clearopbeep(oap);
  741.     goto normal_end;
  742.     }
  743. #ifdef FEAT_CMDWIN
  744.     if (cmdwin_type != 0 && (nv_cmds[idx].cmd_flags & NV_NCW))
  745.     {
  746.     /* This command is not allowed in the cmdline window: beep. */
  747.     clearopbeep(oap);
  748.     EMSG(_(e_cmdwin));
  749.     goto normal_end;
  750.     }
  751. #endif
  752.  
  753. #ifdef FEAT_VISUAL
  754.     /*
  755.      * In Visual/Select mode, a few keys are handled in a special way.
  756.      */
  757.     if (VIsual_active)
  758.     {
  759.     /* when 'keymodel' contains "stopsel" may stop Select/Visual mode */
  760.     if (km_stopsel
  761.         && (nv_cmds[idx].cmd_flags & NV_STS)
  762.         && !(mod_mask & MOD_MASK_SHIFT))
  763.     {
  764.         end_visual_mode();
  765.         redraw_curbuf_later(INVERTED);
  766.     }
  767.  
  768.     /* Keys that work different when 'keymodel' contains "startsel" */
  769.     if (km_startsel)
  770.     {
  771.         if (nv_cmds[idx].cmd_flags & NV_SS)
  772.         {
  773.         unshift_special(&ca);
  774.         idx = find_command(ca.cmdchar);
  775.         }
  776.         else if ((nv_cmds[idx].cmd_flags & NV_SSS)
  777.                            && (mod_mask & MOD_MASK_SHIFT))
  778.         {
  779.         mod_mask &= ~MOD_MASK_SHIFT;
  780.         }
  781.     }
  782.     }
  783. #endif
  784.  
  785. #ifdef FEAT_RIGHTLEFT
  786.     if (curwin->w_p_rl && KeyTyped && !KeyStuffed
  787.                       && (nv_cmds[idx].cmd_flags & NV_RL))
  788.     {
  789.     /* Invert horizontal movements and operations.  Only when typed by the
  790.      * user directly, not when the result of a mapping or "x" translated
  791.      * to "dl". */
  792.     switch (ca.cmdchar)
  793.     {
  794.         case 'l':        ca.cmdchar = 'h'; break;
  795.         case K_RIGHT:   ca.cmdchar = K_LEFT; break;
  796.         case K_S_RIGHT: ca.cmdchar = K_S_LEFT; break;
  797.         case K_C_RIGHT: ca.cmdchar = K_C_LEFT; break;
  798.         case 'h':        ca.cmdchar = 'l'; break;
  799.         case K_LEFT:    ca.cmdchar = K_RIGHT; break;
  800.         case K_S_LEFT:  ca.cmdchar = K_S_RIGHT; break;
  801.         case K_C_LEFT:  ca.cmdchar = K_C_RIGHT; break;
  802.         case '>':        ca.cmdchar = '<'; break;
  803.         case '<':        ca.cmdchar = '>'; break;
  804.     }
  805.     idx = find_command(ca.cmdchar);
  806.     }
  807. #endif
  808.  
  809.     /*
  810.      * Get an additional character if we need one.
  811.      */
  812.     if ((nv_cmds[idx].cmd_flags & NV_NCH)
  813.         && (((nv_cmds[idx].cmd_flags & NV_NCH_NOP) == NV_NCH_NOP
  814.             && oap->op_type == OP_NOP)
  815.         || (nv_cmds[idx].cmd_flags & NV_NCH_ALW) == NV_NCH_ALW
  816.         || (ca.cmdchar == 'q'
  817.             && oap->op_type == OP_NOP
  818.             && !Recording
  819.             && !Exec_reg)
  820.         || ((ca.cmdchar == 'a' || ca.cmdchar == 'i')
  821.             && (oap->op_type != OP_NOP
  822. #ifdef FEAT_VISUAL
  823.             || VIsual_active
  824. #endif
  825.             ))))
  826.     {
  827.     int    *cp;
  828.     int    repl = FALSE;    /* get character for replace mode */
  829.     int    lit = FALSE;    /* get extra character literally */
  830.     int    langmap_active = FALSE;    /* using :lmap mappings */
  831.     int    lang;        /* getting a text character */
  832. #ifdef USE_IM_CONTROL
  833.     int    save_smd;    /* saved value of p_smd */
  834. #endif
  835.  
  836.     ++no_mapping;
  837.     ++allow_keys;        /* no mapping for nchar, but allow key codes */
  838.     if (ca.cmdchar == 'g')
  839.     {
  840.         /*
  841.          * For 'g' get the next character now, so that we can check for
  842.          * "gr", "g'" and "g`".
  843.          */
  844.         ca.nchar = safe_vgetc();
  845. #ifdef FEAT_CMDL_INFO
  846.         need_flushbuf |= add_to_showcmd(ca.nchar);
  847. #endif
  848.         if (ca.nchar == 'r' || ca.nchar == '\'' || ca.nchar == '`')
  849.         {
  850.         cp = &ca.extra_char;    /* need to get a third character */
  851.         if (ca.nchar != 'r')
  852.             lit = TRUE;            /* get it literally */
  853.         else
  854.             repl = TRUE;        /* get it in replace mode */
  855.         }
  856.         else
  857.         cp = NULL;        /* no third character needed */
  858.     }
  859.     else
  860.     {
  861.         if (ca.cmdchar == 'r')        /* get it in replace mode */
  862.         repl = TRUE;
  863.         cp = &ca.nchar;
  864.     }
  865.     lang = (repl || (nv_cmds[idx].cmd_flags & NV_LANG));
  866.  
  867.     /*
  868.      * Get a second or third character.
  869.      */
  870.     if (cp != NULL)
  871.     {
  872. #ifdef CURSOR_SHAPE
  873.         if (repl)
  874.         {
  875.         State = REPLACE;    /* pretend Replace mode */
  876.         ui_cursor_shape();    /* show different cursor shape */
  877.         }
  878. #endif
  879.         if (lang && curbuf->b_p_iminsert == B_IMODE_LMAP)
  880.         {
  881.         /* Allow mappings defined with ":lmap". */
  882.         --no_mapping;
  883.         --allow_keys;
  884.         if (repl)
  885.             State = LREPLACE;
  886.         else
  887.             State = LANGMAP;
  888.         langmap_active = TRUE;
  889.         }
  890. #ifdef USE_IM_CONTROL
  891.         save_smd = p_smd;
  892.         p_smd = FALSE;    /* Don't let the IM code show the mode here */
  893.         if (lang && curbuf->b_p_iminsert == B_IMODE_IM)
  894.         im_set_active(TRUE);
  895. #endif
  896.  
  897.         *cp = safe_vgetc();
  898.  
  899.         if (langmap_active)
  900.         {
  901.         /* Undo the decrement done above */
  902.         ++no_mapping;
  903.         ++allow_keys;
  904.         State = NORMAL_BUSY;
  905.         }
  906. #ifdef USE_IM_CONTROL
  907.         if (lang)
  908.         {
  909.         im_save_status(&curbuf->b_p_iminsert);
  910.         im_set_active(FALSE);
  911.         }
  912.         p_smd = save_smd;
  913. #endif
  914. #ifdef CURSOR_SHAPE
  915.         State = NORMAL_BUSY;
  916. #endif
  917. #ifdef FEAT_CMDL_INFO
  918.         need_flushbuf |= add_to_showcmd(*cp);
  919. #endif
  920.  
  921.         if (!lit)
  922.         {
  923. #ifdef FEAT_DIGRAPHS
  924.         /* Typing CTRL-K gets a digraph. */
  925.         if (*cp == Ctrl_K
  926.             && ((nv_cmds[idx].cmd_flags & NV_LANG)
  927.                 || cp == &ca.extra_char)
  928.             && vim_strchr(p_cpo, CPO_DIGRAPH) == NULL)
  929.         {
  930.             c = get_digraph(FALSE);
  931.             if (c > 0)
  932.             {
  933.             *cp = c;
  934. # ifdef FEAT_CMDL_INFO
  935.             /* Guessing how to update showcmd here... */
  936.             del_from_showcmd(3);
  937.             need_flushbuf |= add_to_showcmd(*cp);
  938. # endif
  939.             }
  940.         }
  941. #endif
  942.  
  943. #ifdef FEAT_LANGMAP
  944.         /* adjust chars > 127, except after "tTfFr" commands */
  945.         LANGMAP_ADJUST(*cp, !lang);
  946. #endif
  947. #ifdef FEAT_RIGHTLEFT
  948.         /* adjust Hebrew mapped char */
  949.         if (p_hkmap && lang && KeyTyped)
  950.             *cp = hkmap(*cp);
  951. # ifdef FEAT_FKMAP
  952.         /* adjust Farsi mapped char */
  953.         if (p_fkmap && lang && KeyTyped)
  954.             *cp = fkmap(*cp);
  955. # endif
  956. #endif
  957.         }
  958.  
  959. #ifdef FEAT_MBYTE
  960.         /* When getting a text character and the next character is a
  961.          * multi-byte character, it could be a composing character.
  962.          * However, don't wait for it to arrive. */
  963.         while (enc_utf8 && lang && (c = vpeekc()) > 0
  964.                  && (c >= 0x100 || MB_BYTE2LEN(vpeekc()) > 1))
  965.         {
  966.         c = safe_vgetc();
  967.         if (!utf_iscomposing(c))
  968.         {
  969.             vungetc(c);        /* it wasn't, put it back */
  970.             break;
  971.         }
  972.         else if (ca.ncharC1 == 0)
  973.             ca.ncharC1 = c;
  974.         else
  975.             ca.ncharC2 = c;
  976.         }
  977. #endif
  978.     }
  979.     --no_mapping;
  980.     --allow_keys;
  981.     }
  982.  
  983. #ifdef FEAT_CMDL_INFO
  984.     /*
  985.      * Flush the showcmd characters onto the screen so we can see them while
  986.      * the command is being executed.  Only do this when the shown command was
  987.      * actually displayed, otherwise this will slow down a lot when executing
  988.      * mappings.
  989.      */
  990.     if (need_flushbuf)
  991.     out_flush();
  992. #endif
  993.  
  994.     State = NORMAL;
  995.  
  996.     if (ca.nchar == ESC)
  997.     {
  998.     clearop(oap);
  999.     if (restart_edit == 0 && goto_im())
  1000.         restart_edit = 'a';
  1001.     goto normal_end;
  1002.     }
  1003.  
  1004.     msg_didout = FALSE;        /* don't scroll screen up for normal command */
  1005.     msg_col = 0;
  1006.  
  1007. #ifdef FEAT_VISUAL
  1008.     old_pos = curwin->w_cursor;        /* remember where cursor was */
  1009.  
  1010.     /* When 'keymodel' contains "startsel" some keys start Select/Visual
  1011.      * mode. */
  1012.     if (!VIsual_active && km_startsel)
  1013.     {
  1014.     if (nv_cmds[idx].cmd_flags & NV_SS)
  1015.     {
  1016.         start_selection();
  1017.         unshift_special(&ca);
  1018.         idx = find_command(ca.cmdchar);
  1019.     }
  1020.     else if ((nv_cmds[idx].cmd_flags & NV_SSS)
  1021.                        && (mod_mask & MOD_MASK_SHIFT))
  1022.     {
  1023.         start_selection();
  1024.         mod_mask &= ~MOD_MASK_SHIFT;
  1025.     }
  1026.     }
  1027. #endif
  1028.  
  1029.     /*
  1030.      * Execute the command!
  1031.      * Call the command function found in the commands table.
  1032.      */
  1033.     ca.arg = nv_cmds[idx].cmd_arg;
  1034.     (nv_cmds[idx].cmd_func)(&ca);
  1035.  
  1036.     /*
  1037.      * If we didn't start or finish an operator, reset oap->regname, unless we
  1038.      * need it later.
  1039.      */
  1040.     if (!finish_op
  1041.         && !oap->op_type
  1042.         && (idx < 0 || !(nv_cmds[idx].cmd_flags & NV_KEEPREG)))
  1043.     {
  1044.     oap->regname = 0;
  1045.     oap->motion_force = NUL;
  1046.     }
  1047.  
  1048.     /*
  1049.      * If an operation is pending, handle it...
  1050.      */
  1051.     do_pending_operator(&ca, old_col, FALSE);
  1052.  
  1053.     /*
  1054.      * Wait for a moment when a message is displayed that will be overwritten
  1055.      * by the mode message.
  1056.      * In Visual mode and with "^O" in Insert mode, a short message will be
  1057.      * overwritten by the mode message.  Wait a bit, until a key is hit.
  1058.      * In Visual mode, it's more important to keep the Visual area updated
  1059.      * than keeping a message (e.g. from a /pat search).
  1060.      * Only do this if the command was typed, not from a mapping.
  1061.      * Don't wait when emsg_silent is non-zero.
  1062.      * Also wait a bit after an error message, e.g. for "^O:".
  1063.      * Don't redraw the screen, it would remove the message.
  1064.      */
  1065.     if (       ((p_smd
  1066.             && (restart_edit != 0
  1067. #ifdef FEAT_VISUAL
  1068.             || (VIsual_active
  1069.                 && old_pos.lnum == curwin->w_cursor.lnum
  1070.                 && old_pos.col == curwin->w_cursor.col)
  1071. #endif
  1072.             )
  1073.             && (clear_cmdline
  1074.             || redraw_cmdline)
  1075.             && msg_didany
  1076.             && !msg_nowait
  1077.             && KeyTyped)
  1078.         || (restart_edit != 0
  1079. #ifdef FEAT_VISUAL
  1080.             && !VIsual_active
  1081. #endif
  1082.             && (msg_scroll
  1083.             || emsg_on_display)))
  1084.         && oap->regname == 0
  1085.         && !(ca.retval & CA_COMMAND_BUSY)
  1086.         && stuff_empty()
  1087.         && typebuf_typed()
  1088.         && emsg_silent == 0
  1089.         && oap->op_type == OP_NOP)
  1090.     {
  1091.     int    save_State = State;
  1092.  
  1093.     /* Draw the cursor with the right shape here */
  1094.     if (restart_edit != 0)
  1095.         State = INSERT;
  1096.  
  1097.     /* If need to redraw, and there is a "keep_msg", redraw before the
  1098.      * delay */
  1099.     if (must_redraw && keep_msg != NULL && !emsg_on_display)
  1100.     {
  1101.         char_u    *kmsg;
  1102.  
  1103.         kmsg = keep_msg;
  1104.         keep_msg = NULL;
  1105.         /* showmode() will clear keep_msg, but we want to use it anyway */
  1106.         update_screen(0);
  1107.         /* now reset it, otherwise it's put in the history again */
  1108.         keep_msg = kmsg;
  1109.         msg_attr(kmsg, keep_msg_attr);
  1110.         vim_free(kmsg);
  1111.     }
  1112.     setcursor();
  1113.     cursor_on();
  1114.     out_flush();
  1115.     if (msg_scroll || emsg_on_display)
  1116.         ui_delay(1000L, TRUE);    /* wait at least one second */
  1117.     ui_delay(3000L, FALSE);        /* wait up to three seconds */
  1118.     State = save_State;
  1119.  
  1120.     msg_scroll = FALSE;
  1121.     emsg_on_display = FALSE;
  1122.     }
  1123.  
  1124.     /*
  1125.      * Finish up after executing a Normal mode command.
  1126.      */
  1127. normal_end:
  1128.  
  1129.     msg_nowait = FALSE;
  1130.  
  1131.     /* Reset finish_op, in case it was set */
  1132. #ifdef CURSOR_SHAPE
  1133.     c = finish_op;
  1134. #endif
  1135.     finish_op = FALSE;
  1136. #ifdef CURSOR_SHAPE
  1137.     /* Redraw the cursor with another shape, if we were in Operator-pending
  1138.      * mode or did a replace command. */
  1139.     if (c || ca.cmdchar == 'r')
  1140.     {
  1141.     ui_cursor_shape();        /* may show different cursor shape */
  1142. # ifdef FEAT_MOUSESHAPE
  1143.     update_mouseshape(-1);
  1144. # endif
  1145.     }
  1146. #endif
  1147.  
  1148. #ifdef FEAT_CMDL_INFO
  1149.     if (oap->op_type == OP_NOP && oap->regname == 0)
  1150.     clear_showcmd();
  1151. #endif
  1152.  
  1153.     checkpcmark();        /* check if we moved since setting pcmark */
  1154.     vim_free(ca.searchbuf);
  1155.  
  1156. #ifdef FEAT_MBYTE
  1157.     if (has_mbyte)
  1158.     mb_adjust_cursor();
  1159. #endif
  1160.  
  1161. #ifdef FEAT_SCROLLBIND
  1162.     if (curwin->w_p_scb && toplevel)
  1163.     {
  1164.     validate_cursor();    /* may need to update w_leftcol */
  1165.     do_check_scrollbind(TRUE);
  1166.     }
  1167. #endif
  1168.  
  1169.     /*
  1170.      * May restart edit(), if we got here with CTRL-O in Insert mode (but not
  1171.      * if still inside a mapping that started in Visual mode).
  1172.      * May switch from Visual to Select mode after CTRL-O command.
  1173.      */
  1174.     if (       oap->op_type == OP_NOP
  1175. #ifdef FEAT_VISUAL
  1176.         && ((restart_edit != 0 && !VIsual_active && old_mapped_len == 0)
  1177.         || restart_VIsual_select == 1)
  1178. #endif
  1179.         && !(ca.retval & CA_COMMAND_BUSY)
  1180.         && stuff_empty()
  1181.         && oap->regname == 0)
  1182.     {
  1183. #ifdef FEAT_VISUAL
  1184.     if (restart_VIsual_select == 1)
  1185.     {
  1186.         VIsual_select = TRUE;
  1187.         showmode();
  1188.         restart_VIsual_select = 0;
  1189.     }
  1190. #endif
  1191.     if (restart_edit != 0
  1192. #ifdef FEAT_VISUAL
  1193.         && !VIsual_active
  1194. #endif
  1195.         && old_mapped_len == 0)
  1196.         (void)edit(restart_edit, FALSE, 1L);
  1197.     }
  1198.  
  1199. #ifdef FEAT_VISUAL
  1200.     if (restart_VIsual_select == 2)
  1201.     restart_VIsual_select = 1;
  1202. #endif
  1203.  
  1204.     /* Save count before an operator for next time. */
  1205.     opcount = ca.opcount;
  1206. }
  1207.  
  1208. /*
  1209.  * Handle an operator after visual mode or when the movement is finished
  1210.  */
  1211.     void
  1212. do_pending_operator(cap, old_col, gui_yank)
  1213.     cmdarg_T    *cap;
  1214.     int        old_col;
  1215.     int        gui_yank;
  1216. {
  1217.     oparg_T    *oap = cap->oap;
  1218.     pos_T    old_cursor;
  1219.     int        empty_region_error;
  1220.     int        restart_edit_save;
  1221.  
  1222. #ifdef FEAT_VISUAL
  1223.     /* The visual area is remembered for redo */
  1224.     static int        redo_VIsual_mode = NUL; /* 'v', 'V', or Ctrl-V */
  1225.     static linenr_T redo_VIsual_line_count; /* number of lines */
  1226.     static colnr_T  redo_VIsual_col;        /* number of cols or end column */
  1227.     static long        redo_VIsual_count;        /* count for Visual operator */
  1228. # ifdef FEAT_VIRTUALEDIT
  1229.     int        include_line_break = FALSE;
  1230. # endif
  1231. #endif
  1232.  
  1233. #if defined(FEAT_CLIPBOARD)
  1234.     /*
  1235.      * Yank the visual area into the GUI selection register before we operate
  1236.      * on it and lose it forever.
  1237.      * Don't do it if a specific register was specified, so that ""x"*P works.
  1238.      * This could call do_pending_operator() recursively, but that's OK
  1239.      * because gui_yank will be TRUE for the nested call.
  1240.      */
  1241.     if (clip_star.available
  1242.         && oap->op_type != OP_NOP
  1243.         && !gui_yank
  1244. # ifdef FEAT_VISUAL
  1245.         && VIsual_active
  1246.         && !redo_VIsual_busy
  1247. # endif
  1248.         && oap->regname == 0)
  1249.     clip_auto_select();
  1250. #endif
  1251.     old_cursor = curwin->w_cursor;
  1252.  
  1253.     /*
  1254.      * If an operation is pending, handle it...
  1255.      */
  1256.     if ((finish_op
  1257. #ifdef FEAT_VISUAL
  1258.         || VIsual_active
  1259. #endif
  1260.         ) && oap->op_type != OP_NOP)
  1261.     {
  1262. #ifdef FEAT_VISUAL
  1263.     oap->is_VIsual = VIsual_active;
  1264.     if (oap->motion_force == 'V')
  1265.         oap->motion_type = MLINE;
  1266.     else if (oap->motion_force == 'v')
  1267.     {
  1268.         /* If the motion was linewise, "inclusive" will not have been set.
  1269.          * Use "exclusive" to be consistent.  Makes "dvj" work nice. */
  1270.         if (oap->motion_type == MLINE)
  1271.         oap->inclusive = FALSE;
  1272.         oap->motion_type = MCHAR;
  1273.     }
  1274.     else if (oap->motion_force == Ctrl_V)
  1275.     {
  1276.         /* Change linewise or characterwise motion into Visual block mode.
  1277.          * */
  1278.         VIsual_active = TRUE;
  1279.         VIsual = oap->start;
  1280.         VIsual_mode = Ctrl_V;
  1281.         VIsual_select = FALSE;
  1282.         VIsual_reselect = FALSE;
  1283.     }
  1284. #endif
  1285.  
  1286.     /* only redo yank when 'y' flag is in 'cpoptions' */
  1287.     /* never redo "zf" (define fold) */
  1288.     if ((vim_strchr(p_cpo, CPO_YANK) != NULL || oap->op_type != OP_YANK)
  1289. #ifdef FEAT_VISUAL
  1290.         && (!VIsual_active || oap->motion_force)
  1291. #endif
  1292. #ifdef FEAT_FOLDING
  1293.         && oap->op_type != OP_FOLD
  1294.         && oap->op_type != OP_FOLDOPEN
  1295.         && oap->op_type != OP_FOLDOPENREC
  1296.         && oap->op_type != OP_FOLDCLOSE
  1297.         && oap->op_type != OP_FOLDCLOSEREC
  1298.         && oap->op_type != OP_FOLDDEL
  1299.         && oap->op_type != OP_FOLDDELREC
  1300. #endif
  1301.         )
  1302.     {
  1303.         prep_redo(oap->regname, cap->count0,
  1304.             get_op_char(oap->op_type), get_extra_op_char(oap->op_type),
  1305.             oap->motion_force, cap->cmdchar, cap->nchar);
  1306.         if (cap->cmdchar == '/' || cap->cmdchar == '?') /* was a search */
  1307.         {
  1308.         /*
  1309.          * If 'cpoptions' does not contain 'r', insert the search
  1310.          * pattern to really repeat the same command.
  1311.          */
  1312.         if (vim_strchr(p_cpo, CPO_REDO) == NULL)
  1313.             AppendToRedobuffLit(cap->searchbuf);
  1314.         AppendToRedobuff(NL_STR);
  1315.         }
  1316.     }
  1317.  
  1318. #ifdef FEAT_VISUAL
  1319.     if (redo_VIsual_busy)
  1320.     {
  1321.         oap->start = curwin->w_cursor;
  1322.         curwin->w_cursor.lnum += redo_VIsual_line_count - 1;
  1323.         if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
  1324.         curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
  1325.         VIsual_mode = redo_VIsual_mode;
  1326.         if (VIsual_mode == 'v')
  1327.         {
  1328.         if (redo_VIsual_line_count <= 1)
  1329.             curwin->w_cursor.col += redo_VIsual_col - 1;
  1330.         else
  1331.             curwin->w_cursor.col = redo_VIsual_col;
  1332.         }
  1333.         if (redo_VIsual_col == MAXCOL)
  1334.         {
  1335.         curwin->w_curswant = MAXCOL;
  1336.         coladvance((colnr_T)MAXCOL);
  1337.         }
  1338.         cap->count0 = redo_VIsual_count;
  1339.         if (redo_VIsual_count != 0)
  1340.         cap->count1 = redo_VIsual_count;
  1341.         else
  1342.         cap->count1 = 1;
  1343.     }
  1344.     else if (VIsual_active)
  1345.     {
  1346.         /* Save the current VIsual area for '< and '> marks, and "gv" */
  1347.         curbuf->b_visual_start = VIsual;
  1348.         curbuf->b_visual_end = curwin->w_cursor;
  1349.         curbuf->b_visual_mode = VIsual_mode;
  1350.         curbuf->b_visual_curswant = curwin->w_curswant;
  1351.  
  1352.         /* In Select mode, a linewise selection is operated upon like a
  1353.          * characterwise selection. */
  1354.         if (VIsual_select && VIsual_mode == 'V')
  1355.         {
  1356.         if (lt(VIsual, curwin->w_cursor))
  1357.         {
  1358.             VIsual.col = 0;
  1359.             curwin->w_cursor.col =
  1360.                    (colnr_T)STRLEN(ml_get(curwin->w_cursor.lnum));
  1361.         }
  1362.         else
  1363.         {
  1364.             curwin->w_cursor.col = 0;
  1365.             VIsual.col = (colnr_T)STRLEN(ml_get(VIsual.lnum));
  1366.         }
  1367.         VIsual_mode = 'v';
  1368.         }
  1369.         /* If 'selection' is "exclusive", backup one character for
  1370.          * charwise selections. */
  1371.         else if (VIsual_mode == 'v')
  1372.         {
  1373. # ifdef FEAT_VIRTUALEDIT
  1374.         include_line_break =
  1375. # endif
  1376.             unadjust_for_sel();
  1377.         }
  1378.  
  1379.         oap->start = VIsual;
  1380.         if (VIsual_mode == 'V')
  1381.         oap->start.col = 0;
  1382.     }
  1383. #endif /* FEAT_VISUAL */
  1384.  
  1385.     /*
  1386.      * Set oap->start to the first position of the operated text, oap->end
  1387.      * to the end of the operated text.  w_cursor is equal to oap->start.
  1388.      */
  1389.     if (lt(oap->start, curwin->w_cursor))
  1390.     {
  1391. #ifdef FEAT_FOLDING
  1392.         /* Include folded lines completely. */
  1393.         if (!VIsual_active)
  1394.         {
  1395.         if (hasFolding(oap->start.lnum, &oap->start.lnum, NULL))
  1396.             oap->start.col = 0;
  1397.         if (hasFolding(curwin->w_cursor.lnum, NULL,
  1398.                               &curwin->w_cursor.lnum))
  1399.             curwin->w_cursor.col = (colnr_T)STRLEN(ml_get_curline());
  1400.         }
  1401. #endif
  1402.         oap->end = curwin->w_cursor;
  1403.         curwin->w_cursor = oap->start;
  1404.     }
  1405.     else
  1406.     {
  1407. #ifdef FEAT_FOLDING
  1408.         /* Include folded lines completely. */
  1409.         if (!VIsual_active && oap->motion_type == MLINE)
  1410.         {
  1411.         if (hasFolding(curwin->w_cursor.lnum, &curwin->w_cursor.lnum,
  1412.                                     NULL))
  1413.             curwin->w_cursor.col = 0;
  1414.         if (hasFolding(oap->start.lnum, NULL, &oap->start.lnum))
  1415.             oap->start.col = (colnr_T)STRLEN(ml_get(oap->start.lnum));
  1416.         }
  1417. #endif
  1418.         oap->end = oap->start;
  1419.         oap->start = curwin->w_cursor;
  1420.     }
  1421.  
  1422.     oap->line_count = oap->end.lnum - oap->start.lnum + 1;
  1423.  
  1424. #ifdef FEAT_VISUAL
  1425.     if (VIsual_active || redo_VIsual_busy)
  1426.     {
  1427.         if (VIsual_mode == Ctrl_V)    /* block mode */
  1428.         {
  1429.         colnr_T        start, end;
  1430.  
  1431.         oap->block_mode = TRUE;
  1432.  
  1433.         getvvcol(curwin, &(oap->start),
  1434.                       &oap->start_vcol, NULL, &oap->end_vcol);
  1435.         if (!redo_VIsual_busy)
  1436.         {
  1437.             getvvcol(curwin, &(oap->end), &start, NULL, &end);
  1438.  
  1439.             if (start < oap->start_vcol)
  1440.             oap->start_vcol = start;
  1441.             if (end > oap->end_vcol)
  1442.             {
  1443.             if (*p_sel == 'e' && start - 1 >= oap->end_vcol)
  1444.                 oap->end_vcol = start - 1;
  1445.             else
  1446.                 oap->end_vcol = end;
  1447.             }
  1448.         }
  1449.  
  1450.         /* if '$' was used, get oap->end_vcol from longest line */
  1451.         if (curwin->w_curswant == MAXCOL)
  1452.         {
  1453.             curwin->w_cursor.col = MAXCOL;
  1454.             oap->end_vcol = 0;
  1455.             for (curwin->w_cursor.lnum = oap->start.lnum;
  1456.                 curwin->w_cursor.lnum <= oap->end.lnum;
  1457.                               ++curwin->w_cursor.lnum)
  1458.             {
  1459.             getvvcol(curwin, &curwin->w_cursor, NULL, NULL, &end);
  1460.             if (end > oap->end_vcol)
  1461.                 oap->end_vcol = end;
  1462.             }
  1463.         }
  1464.         else if (redo_VIsual_busy)
  1465.             oap->end_vcol = oap->start_vcol + redo_VIsual_col - 1;
  1466.         /*
  1467.          * Correct oap->end.col and oap->start.col to be the
  1468.          * upper-left and lower-right corner of the block area.
  1469.          *
  1470.          * (Actually, this does convert column positions into character
  1471.          * positions)
  1472.          */
  1473.         curwin->w_cursor.lnum = oap->end.lnum;
  1474.         coladvance(oap->end_vcol);
  1475.         oap->end = curwin->w_cursor;
  1476.  
  1477.         curwin->w_cursor = oap->start;
  1478.         coladvance(oap->start_vcol);
  1479.         oap->start = curwin->w_cursor;
  1480.         }
  1481.  
  1482.         if (!redo_VIsual_busy && !gui_yank)
  1483.         {
  1484.         /*
  1485.          * Prepare to reselect and redo Visual: this is based on the
  1486.          * size of the Visual text
  1487.          */
  1488.         resel_VIsual_mode = VIsual_mode;
  1489.         if (curwin->w_curswant == MAXCOL)
  1490.             resel_VIsual_col = MAXCOL;
  1491.         else if (VIsual_mode == Ctrl_V)
  1492.             resel_VIsual_col = oap->end_vcol - oap->start_vcol + 1;
  1493.         else if (oap->line_count > 1)
  1494.             resel_VIsual_col = oap->end.col;
  1495.         else
  1496.             resel_VIsual_col = oap->end.col - oap->start.col + 1;
  1497.         resel_VIsual_line_count = oap->line_count;
  1498.         }
  1499.  
  1500.         /* can't redo yank (unless 'y' is in 'cpoptions') and ":" */
  1501.         if ((vim_strchr(p_cpo, CPO_YANK) != NULL || oap->op_type != OP_YANK)
  1502.             && oap->op_type != OP_COLON
  1503. #ifdef FEAT_FOLDING
  1504.             && oap->op_type != OP_FOLD
  1505.             && oap->op_type != OP_FOLDOPEN
  1506.             && oap->op_type != OP_FOLDOPENREC
  1507.             && oap->op_type != OP_FOLDCLOSE
  1508.             && oap->op_type != OP_FOLDCLOSEREC
  1509.             && oap->op_type != OP_FOLDDEL
  1510.             && oap->op_type != OP_FOLDDELREC
  1511. #endif
  1512.             && oap->motion_force == NUL
  1513.             )
  1514.         {
  1515.         prep_redo(oap->regname, 0L, NUL, 'v', NUL,
  1516.             get_op_char(oap->op_type),
  1517.                          get_extra_op_char(oap->op_type));
  1518.         redo_VIsual_mode = resel_VIsual_mode;
  1519.         redo_VIsual_col = resel_VIsual_col;
  1520.         redo_VIsual_line_count = resel_VIsual_line_count;
  1521.         redo_VIsual_count = cap->count0;
  1522.         }
  1523.  
  1524.         /*
  1525.          * oap->inclusive defaults to TRUE.
  1526.          * If oap->end is on a NUL (empty line) oap->inclusive becomes
  1527.          * FALSE.  This makes "d}P" and "v}dP" work the same.
  1528.          */
  1529.         if (oap->motion_force == NUL || oap->motion_type == MLINE)
  1530.         oap->inclusive = TRUE;
  1531.         if (virtual_active() && curwin->w_curswant == MAXCOL)
  1532.         oap->inclusive = FALSE;
  1533.         if (VIsual_mode == 'V')
  1534.         oap->motion_type = MLINE;
  1535.         else
  1536.         {
  1537.         oap->motion_type = MCHAR;
  1538.         if (VIsual_mode != Ctrl_V && *ml_get_pos(&(oap->end)) == NUL
  1539. # ifdef FEAT_VIRTUALEDIT
  1540.             && (include_line_break || !virtual_active())
  1541. # endif
  1542.             )
  1543.         {
  1544.             oap->inclusive = FALSE;
  1545.             /* Try to include the newline, unless it's an operator
  1546.              * that works on lines only */
  1547.             if (*p_sel != 'o'
  1548.                 && !op_on_lines(oap->op_type)
  1549.                 && oap->end.lnum < curbuf->b_ml.ml_line_count)
  1550.             {
  1551.             ++oap->end.lnum;
  1552.             oap->end.col = 0;
  1553. # ifdef FEAT_VIRTUALEDIT
  1554.             oap->end.coladd = 0;
  1555. # endif
  1556.             ++oap->line_count;
  1557.             }
  1558.         }
  1559.         }
  1560.  
  1561.         redo_VIsual_busy = FALSE;
  1562.         /*
  1563.          * Switch Visual off now, so screen updating does
  1564.          * not show inverted text when the screen is redrawn.
  1565.          * With OP_YANK and sometimes with OP_COLON and OP_FILTER there is
  1566.          * no screen redraw, so it is done here to remove the inverted
  1567.          * part.
  1568.          */
  1569.         if (!gui_yank)
  1570.         {
  1571.         VIsual_active = FALSE;
  1572. # ifdef FEAT_MOUSE
  1573.         setmouse();
  1574.         mouse_dragging = 0;
  1575. # endif
  1576.         if (p_smd)
  1577.             clear_cmdline = TRUE;   /* unshow visual mode later */
  1578. #ifdef FEAT_CMDL_INFO
  1579.         else
  1580.             clear_showcmd();
  1581. #endif
  1582.         if ((oap->op_type == OP_YANK
  1583.                 || oap->op_type == OP_COLON
  1584.                 || oap->op_type == OP_FILTER)
  1585.             && oap->motion_force == NUL)
  1586.             redraw_curbuf_later(INVERTED);
  1587.         }
  1588.     }
  1589. #endif
  1590.  
  1591. #ifdef FEAT_MBYTE
  1592.     /* Include the trailing byte of a multi-byte char.  Don't do it when
  1593.      * VIsual_active is TRUE and 'sel' is "exclusive", the position has
  1594.      * already been moved to the trailing byte by adjust_for_sel() then. */
  1595.     if (has_mbyte && oap->inclusive
  1596. # ifdef FEAT_VISUAL
  1597.             && (!oap->is_VIsual || *p_sel != 'e')
  1598. # endif
  1599.             )
  1600.     {
  1601.         int        l;
  1602.  
  1603.         l = (*mb_ptr2len_check)(ml_get_pos(&oap->end));
  1604.         if (l > 1)
  1605.         oap->end.col += l - 1;
  1606.     }
  1607. #endif
  1608.     curwin->w_set_curswant = TRUE;
  1609.  
  1610.     /*
  1611.      * oap->empty is set when start and end are the same.  The inclusive
  1612.      * flag affects this too, unless yanking and the end is on a NUL.
  1613.      */
  1614.     oap->empty = (oap->motion_type == MCHAR
  1615.             && (!oap->inclusive
  1616.             || (oap->op_type == OP_YANK
  1617.                 && gchar_pos(&oap->end) == NUL))
  1618.             && equal(oap->start, oap->end)
  1619. #ifdef FEAT_VIRTUALEDIT
  1620.             && !(virtual_active()
  1621.             && oap->start.coladd != oap->end.coladd)
  1622. #endif
  1623.             );
  1624.     /*
  1625.      * For delete, change and yank, it's an error to operate on an
  1626.      * empty region, when 'E' inclucded in 'cpoptions' (Vi compatible).
  1627.      */
  1628.     empty_region_error = (oap->empty
  1629.                 && vim_strchr(p_cpo, CPO_EMPTYREGION) != NULL);
  1630.  
  1631. #ifdef FEAT_VISUAL
  1632.     /* Force a redraw when operating on an empty Visual region or when
  1633.      * 'modifiable is off. */
  1634.     if (oap->is_VIsual && (oap->empty || !curbuf->b_p_ma))
  1635.         redraw_curbuf_later(INVERTED);
  1636. #endif
  1637.  
  1638.     /*
  1639.      * If the end of an operator is in column one while oap->motion_type
  1640.      * is MCHAR and oap->inclusive is FALSE, we put op_end after the last
  1641.      * character in the previous line. If op_start is on or before the
  1642.      * first non-blank in the line, the operator becomes linewise
  1643.      * (strange, but that's the way vi does it).
  1644.      */
  1645.     if (       oap->motion_type == MCHAR
  1646.         && oap->inclusive == FALSE
  1647.         && !(cap->retval & CA_NO_ADJ_OP_END)
  1648.         && oap->end.col == 0
  1649. #ifdef FEAT_VISUAL
  1650.         && (!oap->is_VIsual || *p_sel == 'o')
  1651. #endif
  1652.         && oap->line_count > 1)
  1653.     {
  1654.         oap->end_adjusted = TRUE;        /* remember that we did this */
  1655.         --oap->line_count;
  1656.         --oap->end.lnum;
  1657.         if (inindent(0))
  1658.         oap->motion_type = MLINE;
  1659.         else
  1660.         {
  1661.         oap->end.col = (colnr_T)STRLEN(ml_get(oap->end.lnum));
  1662.         if (oap->end.col)
  1663.         {
  1664.             --oap->end.col;
  1665.             oap->inclusive = TRUE;
  1666.         }
  1667.         }
  1668.     }
  1669.     else
  1670.         oap->end_adjusted = FALSE;
  1671.  
  1672.     switch (oap->op_type)
  1673.     {
  1674.     case OP_LSHIFT:
  1675.     case OP_RSHIFT:
  1676.         op_shift(oap, TRUE,
  1677. #ifdef FEAT_VISUAL
  1678.             oap->is_VIsual ? (int)cap->count1 :
  1679. #endif
  1680.             1);
  1681.         break;
  1682.  
  1683.     case OP_JOIN_NS:
  1684.     case OP_JOIN:
  1685.         if (oap->line_count < 2)
  1686.         oap->line_count = 2;
  1687.         if (curwin->w_cursor.lnum + oap->line_count - 1 >
  1688.                            curbuf->b_ml.ml_line_count)
  1689.         beep_flush();
  1690.         else
  1691.         do_do_join(oap->line_count, oap->op_type == OP_JOIN);
  1692.         break;
  1693.  
  1694.     case OP_DELETE:
  1695. #ifdef FEAT_VISUAL
  1696.         VIsual_reselect = FALSE;        /* don't reselect now */
  1697. #endif
  1698.         if (empty_region_error)
  1699.         vim_beep();
  1700.         else
  1701.         (void)op_delete(oap);
  1702.         break;
  1703.  
  1704.     case OP_YANK:
  1705.         if (empty_region_error)
  1706.         {
  1707.         if (!gui_yank)
  1708.             vim_beep();
  1709.         }
  1710.         else
  1711.         (void)op_yank(oap, FALSE, !gui_yank);
  1712.         check_cursor_col();
  1713.         break;
  1714.  
  1715.     case OP_CHANGE:
  1716. #ifdef FEAT_VISUAL
  1717.         VIsual_reselect = FALSE;        /* don't reselect now */
  1718. #endif
  1719.         if (empty_region_error)
  1720.         vim_beep();
  1721.         else
  1722.         {
  1723.         /* This is a new edit command, not a restart.  Need to
  1724.          * remember it to make 'insertmode' work with mappings for
  1725.          * Visual mode.  But do this only once. */
  1726.         restart_edit_save = restart_edit;
  1727.         restart_edit = 0;
  1728.         if (op_change(oap))    /* will call edit() */
  1729.             cap->retval |= CA_COMMAND_BUSY;
  1730.         if (restart_edit == 0)
  1731.             restart_edit = restart_edit_save;
  1732.         }
  1733.         break;
  1734.  
  1735.     case OP_FILTER:
  1736.         if (vim_strchr(p_cpo, CPO_FILTER) != NULL)
  1737.         AppendToRedobuff((char_u *)"!\r");  /* use any last used !cmd */
  1738.         else
  1739.         bangredo = TRUE;    /* do_bang() will put cmd in redo buffer */
  1740.  
  1741.     case OP_INDENT:
  1742.     case OP_COLON:
  1743.  
  1744. #if defined(FEAT_LISP) || defined(FEAT_CINDENT)
  1745.         /*
  1746.          * If 'equalprg' is empty, do the indenting internally.
  1747.          */
  1748.         if (oap->op_type == OP_INDENT && *get_equalprg() == NUL)
  1749.         {
  1750. # ifdef FEAT_LISP
  1751.         if (curbuf->b_p_lisp)
  1752.         {
  1753.             op_reindent(oap, get_lisp_indent);
  1754.             break;
  1755.         }
  1756. # endif
  1757. # ifdef FEAT_CINDENT
  1758.         op_reindent(oap,
  1759. #  ifdef FEAT_EVAL
  1760.             *curbuf->b_p_inde != NUL ? get_expr_indent :
  1761. #  endif
  1762.                 get_c_indent);
  1763.         break;
  1764. # endif
  1765.         }
  1766. #endif
  1767.  
  1768.         op_colon(oap);
  1769.         break;
  1770.  
  1771.     case OP_TILDE:
  1772.     case OP_UPPER:
  1773.     case OP_LOWER:
  1774.     case OP_ROT13:
  1775.         if (empty_region_error)
  1776.         vim_beep();
  1777.         else
  1778.         op_tilde(oap);
  1779.         check_cursor_col();
  1780.         break;
  1781.  
  1782.     case OP_FORMAT:
  1783.         if (*p_fp != NUL)
  1784.         op_colon(oap);        /* use external command */
  1785.         else
  1786.         op_format(oap);        /* use internal function */
  1787.         break;
  1788.  
  1789.     case OP_INSERT:
  1790.     case OP_APPEND:
  1791. #ifdef FEAT_VISUAL
  1792.         VIsual_reselect = FALSE;    /* don't reselect now */
  1793. #endif
  1794. #ifdef FEAT_VISUALEXTRA
  1795.         if (empty_region_error)
  1796. #endif
  1797.         vim_beep();
  1798. #ifdef FEAT_VISUALEXTRA
  1799.         else
  1800.         {
  1801.         /* This is a new edit command, not a restart.  Need to
  1802.          * remember it to make 'insertmode' work with mappings for
  1803.          * Visual mode.  But do this only once. */
  1804.         restart_edit_save = restart_edit;
  1805.         restart_edit = 0;
  1806.         op_insert(oap, cap->count1);/* handles insert & append
  1807.                          * will call edit() */
  1808.         if (restart_edit == 0)
  1809.             restart_edit = restart_edit_save;
  1810.         }
  1811. #endif
  1812.         break;
  1813.  
  1814.     case OP_REPLACE:
  1815. #ifdef FEAT_VISUAL
  1816.         VIsual_reselect = FALSE;    /* don't reselect now */
  1817. #endif
  1818. #ifdef FEAT_VISUALEXTRA
  1819.         if (empty_region_error)
  1820. #endif
  1821.         vim_beep();
  1822. #ifdef FEAT_VISUALEXTRA
  1823.         else
  1824.         op_replace(oap, cap->nchar);
  1825. #endif
  1826.         break;
  1827.  
  1828. #ifdef FEAT_FOLDING
  1829.     case OP_FOLD:
  1830.         VIsual_reselect = FALSE;    /* don't reselect now */
  1831.         foldCreate(oap->start.lnum, oap->end.lnum);
  1832.         break;
  1833.  
  1834.     case OP_FOLDOPEN:
  1835.     case OP_FOLDOPENREC:
  1836.     case OP_FOLDCLOSE:
  1837.     case OP_FOLDCLOSEREC:
  1838.         VIsual_reselect = FALSE;    /* don't reselect now */
  1839.         opFoldRange(oap->start.lnum, oap->end.lnum,
  1840.             oap->op_type == OP_FOLDOPEN
  1841.                         || oap->op_type == OP_FOLDOPENREC,
  1842.             oap->op_type == OP_FOLDOPENREC
  1843.                       || oap->op_type == OP_FOLDCLOSEREC,
  1844.                       oap->is_VIsual);
  1845.         break;
  1846.  
  1847.     case OP_FOLDDEL:
  1848.     case OP_FOLDDELREC:
  1849.         VIsual_reselect = FALSE;    /* don't reselect now */
  1850.         deleteFold(oap->start.lnum, oap->end.lnum,
  1851.                    oap->op_type == OP_FOLDDELREC, oap->is_VIsual);
  1852.         break;
  1853. #endif
  1854.     default:
  1855.         clearopbeep(oap);
  1856.     }
  1857.     if (!gui_yank)
  1858.     {
  1859.         /*
  1860.          * if 'sol' not set, go back to old column for some commands
  1861.          */
  1862.         if (!p_sol && oap->motion_type == MLINE && !oap->end_adjusted
  1863.             && (oap->op_type == OP_LSHIFT || oap->op_type == OP_RSHIFT
  1864.                         || oap->op_type == OP_DELETE))
  1865.         coladvance(curwin->w_curswant = old_col);
  1866.         oap->op_type = OP_NOP;
  1867.     }
  1868.     else
  1869.     {
  1870.         curwin->w_cursor = old_cursor;
  1871.     }
  1872.     oap->block_mode = FALSE;
  1873.     oap->regname = 0;
  1874.     oap->motion_force = NUL;
  1875.     }
  1876. }
  1877.  
  1878. /*
  1879.  * Handle indent and format operators and visual mode ":".
  1880.  */
  1881.     static void
  1882. op_colon(oap)
  1883.     oparg_T    *oap;
  1884. {
  1885.     stuffcharReadbuff(':');
  1886. #ifdef FEAT_VISUAL
  1887.     if (oap->is_VIsual)
  1888.     stuffReadbuff((char_u *)"'<,'>");
  1889.     else
  1890. #endif
  1891.     {
  1892.     /*
  1893.      * Make the range look nice, so it can be repeated.
  1894.      */
  1895.     if (oap->start.lnum == curwin->w_cursor.lnum)
  1896.         stuffcharReadbuff('.');
  1897.     else
  1898.         stuffnumReadbuff((long)oap->start.lnum);
  1899.     if (oap->end.lnum != oap->start.lnum)
  1900.     {
  1901.         stuffcharReadbuff(',');
  1902.         if (oap->end.lnum == curwin->w_cursor.lnum)
  1903.         stuffcharReadbuff('.');
  1904.         else if (oap->end.lnum == curbuf->b_ml.ml_line_count)
  1905.         stuffcharReadbuff('$');
  1906.         else if (oap->start.lnum == curwin->w_cursor.lnum)
  1907.         {
  1908.         stuffReadbuff((char_u *)".+");
  1909.         stuffnumReadbuff((long)oap->line_count - 1);
  1910.         }
  1911.         else
  1912.         stuffnumReadbuff((long)oap->end.lnum);
  1913.     }
  1914.     }
  1915.     if (oap->op_type != OP_COLON)
  1916.     stuffReadbuff((char_u *)"!");
  1917.     if (oap->op_type == OP_INDENT)
  1918.     {
  1919. #ifndef FEAT_CINDENT
  1920.     if (*get_equalprg() == NUL)
  1921.         stuffReadbuff((char_u *)"indent");
  1922.     else
  1923. #endif
  1924.         stuffReadbuff(get_equalprg());
  1925.     stuffReadbuff((char_u *)"\n");
  1926.     }
  1927.     else if (oap->op_type == OP_FORMAT)
  1928.     {
  1929.     if (*p_fp == NUL)
  1930.         stuffReadbuff((char_u *)"fmt");
  1931.     else
  1932.         stuffReadbuff(p_fp);
  1933.     stuffReadbuff((char_u *)"\n");
  1934.     }
  1935.  
  1936.     /*
  1937.      * do_cmdline() does the rest
  1938.      */
  1939. }
  1940.  
  1941. #if defined(FEAT_MOUSE) || defined(PROTO)
  1942. /*
  1943.  * Do the appropriate action for the current mouse click in the current mode.
  1944.  * Not used for Command-line mode.
  1945.  *
  1946.  * Normal Mode:
  1947.  * event     modi-    position      visual       change   action
  1948.  *         fier    cursor               window
  1949.  * left press      -    yes        end            yes
  1950.  * left press      C    yes        end            yes        "^]" (2)
  1951.  * left press      S    yes        end            yes        "*" (2)
  1952.  * left drag      -    yes    start if moved        no
  1953.  * left relse      -    yes    start if moved        no
  1954.  * middle press      -    yes     if not active        no        put register
  1955.  * middle press      -    yes     if active        no        yank and put
  1956.  * right press      -    yes    start or extend        yes
  1957.  * right press      S    yes    no change        yes        "#" (2)
  1958.  * right drag      -    yes    extend            no
  1959.  * right relse      -    yes    extend            no
  1960.  *
  1961.  * Insert or Replace Mode:
  1962.  * event     modi-    position      visual       change   action
  1963.  *         fier    cursor               window
  1964.  * left press      -    yes    (cannot be active)  yes
  1965.  * left press      C    yes    (cannot be active)  yes        "CTRL-O^]" (2)
  1966.  * left press      S    yes    (cannot be active)  yes        "CTRL-O*" (2)
  1967.  * left drag      -    yes    start or extend (1) no        CTRL-O (1)
  1968.  * left relse      -    yes    start or extend (1) no        CTRL-O (1)
  1969.  * middle press      -    no    (cannot be active)  no        put register
  1970.  * right press      -    yes    start or extend        yes        CTRL-O
  1971.  * right press      S    yes    (cannot be active)  yes        "CTRL-O#" (2)
  1972.  *
  1973.  * (1) only if mouse pointer moved since press
  1974.  * (2) only if click is in same buffer
  1975.  *
  1976.  * Return TRUE if start_arrow() should be called for edit mode.
  1977.  */
  1978.     int
  1979. do_mouse(oap, c, dir, count, fixindent)
  1980.     oparg_T    *oap;        /* operator argument, can be NULL */
  1981.     int        c;        /* K_LEFTMOUSE, etc */
  1982.     int        dir;        /* Direction to 'put' if necessary */
  1983.     long    count;
  1984.     int        fixindent;    /* PUT_FIXINDENT if fixing indent necessary */
  1985. {
  1986.     static int    do_always = FALSE;    /* ignore 'mouse' setting next time */
  1987.     static int    got_click = FALSE;    /* got a click some time back */
  1988.  
  1989.     int        which_button;    /* MOUSE_LEFT, _MIDDLE or _RIGHT */
  1990.     int        is_click;    /* If FALSE it's a drag or release event */
  1991.     int        is_drag;    /* If TRUE it's a drag event */
  1992.     int        jump_flags = 0;    /* flags for jump_to_mouse() */
  1993.     pos_T    start_visual;
  1994.     int        moved;        /* Has cursor moved? */
  1995.     int        in_status_line;    /* mouse in status line */
  1996. #ifdef FEAT_VERTSPLIT
  1997.     int        in_sep_line;    /* mouse in vertical separator line */
  1998. #endif
  1999.     int        c1, c2;
  2000. #if defined(FEAT_FOLDING)
  2001.     pos_T    save_cursor;
  2002. #endif
  2003.     win_T    *old_curwin = curwin;
  2004. #ifdef FEAT_VISUAL
  2005.     static pos_T orig_cursor;
  2006.     colnr_T    leftcol, rightcol;
  2007.     pos_T    end_visual;
  2008.     int        diff;
  2009.     int        old_active = VIsual_active;
  2010.     int        old_mode = VIsual_mode;
  2011. #endif
  2012.     int        regname;
  2013.  
  2014. #if defined(FEAT_FOLDING)
  2015.     save_cursor = curwin->w_cursor;
  2016. #endif
  2017.  
  2018.     /*
  2019.      * When GUI is active, always recognize mouse events, otherwise:
  2020.      * - Ignore mouse event in normal mode if 'mouse' doesn't include 'n'.
  2021.      * - Ignore mouse event in visual mode if 'mouse' doesn't include 'v'.
  2022.      * - For command line and insert mode 'mouse' is checked before calling
  2023.      *     do_mouse().
  2024.      */
  2025.     if (do_always)
  2026.     do_always = FALSE;
  2027.     else
  2028. #ifdef FEAT_GUI
  2029.     if (!gui.in_use)
  2030. #endif
  2031.     {
  2032. #ifdef FEAT_VISUAL
  2033.         if (VIsual_active)
  2034.         {
  2035.         if (!mouse_has(MOUSE_VISUAL))
  2036.             return FALSE;
  2037.         }
  2038.         else
  2039. #endif
  2040.         if (State == NORMAL && !mouse_has(MOUSE_NORMAL))
  2041.         return FALSE;
  2042.     }
  2043.  
  2044.     which_button = get_mouse_button(KEY2TERMCAP1(c), &is_click, &is_drag);
  2045.  
  2046. #ifdef FEAT_MOUSESHAPE
  2047.     /* May have stopped dragging the status or separator line.  The pointer is
  2048.      * most likely still on the status or separator line. */
  2049.     if (!is_drag && drag_status_line)
  2050.     {
  2051.     drag_status_line = FALSE;
  2052.     update_mouseshape(SHAPE_IDX_STATUS);
  2053.     }
  2054. # ifdef FEAT_VERTSPLIT
  2055.     if (!is_drag && drag_sep_line)
  2056.     {
  2057.     drag_sep_line = FALSE;
  2058.     update_mouseshape(SHAPE_IDX_VSEP);
  2059.     }
  2060. # endif
  2061. #endif
  2062.  
  2063.     /*
  2064.      * Ignore drag and release events if we didn't get a click.
  2065.      */
  2066.     if (is_click)
  2067.     got_click = TRUE;
  2068.     else
  2069.     {
  2070.     if (!got_click)            /* didn't get click, ignore */
  2071.         return FALSE;
  2072.     if (!is_drag)            /* release, reset got_click */
  2073.         got_click = FALSE;
  2074.     }
  2075.  
  2076.     /*
  2077.      * ALT is currently ignored
  2078.      */
  2079.     if ((mod_mask & MOD_MASK_ALT))
  2080.     return FALSE;
  2081.  
  2082.     /*
  2083.      * CTRL right mouse button does CTRL-T
  2084.      */
  2085.     if (is_click && (mod_mask & MOD_MASK_CTRL) && which_button == MOUSE_RIGHT)
  2086.     {
  2087.     if (State & INSERT)
  2088.         stuffcharReadbuff(Ctrl_O);
  2089.     if (count > 1)
  2090.         stuffnumReadbuff(count);
  2091.     stuffcharReadbuff(Ctrl_T);
  2092.     got_click = FALSE;        /* ignore drag&release now */
  2093.     return FALSE;
  2094.     }
  2095.  
  2096.     /*
  2097.      * CTRL only works with left mouse button
  2098.      */
  2099.     if ((mod_mask & MOD_MASK_CTRL) && which_button != MOUSE_LEFT)
  2100.     return FALSE;
  2101.  
  2102.     /*
  2103.      * When a modifier is down, ignore drag and release events, as well as
  2104.      * multiple clicks and the middle mouse button.
  2105.      * Accept shift-leftmouse drags when 'mousemodel' is "popup.*".
  2106.      */
  2107.     if ((mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL | MOD_MASK_ALT))
  2108.         && (!is_click
  2109.         || (mod_mask & MOD_MASK_MULTI_CLICK)
  2110.         || which_button == MOUSE_MIDDLE)
  2111.         && !((mod_mask & MOD_MASK_SHIFT)
  2112.         && mouse_model_popup()
  2113.         && which_button == MOUSE_LEFT)
  2114.         )
  2115.     return FALSE;
  2116.  
  2117.     /*
  2118.      * If the button press was used as the movement command for an operator
  2119.      * (eg "d<MOUSE>"), or it is the middle button that is held down, ignore
  2120.      * drag/release events.
  2121.      */
  2122.     if (!is_click && which_button == MOUSE_MIDDLE)
  2123.     return FALSE;
  2124.  
  2125.     if (oap != NULL)
  2126.     regname = oap->regname;
  2127.     else
  2128.     regname = 0;
  2129.  
  2130.     /*
  2131.      * Middle mouse button does a 'put' of the selected text
  2132.      */
  2133.     if (which_button == MOUSE_MIDDLE)
  2134.     {
  2135.     if (State == NORMAL)
  2136.     {
  2137.         /*
  2138.          * If an operator was pending, we don't know what the user wanted
  2139.          * to do. Go back to normal mode: Clear the operator and beep().
  2140.          */
  2141.         if (oap != NULL && oap->op_type != OP_NOP)
  2142.         {
  2143.         clearopbeep(oap);
  2144.         return FALSE;
  2145.         }
  2146.  
  2147. #ifdef FEAT_VISUAL
  2148.         /*
  2149.          * If visual was active, yank the highlighted text and put it
  2150.          * before the mouse pointer position.
  2151.          */
  2152.         if (VIsual_active)
  2153.         {
  2154.         stuffcharReadbuff('y');
  2155.         stuffcharReadbuff(K_MIDDLEMOUSE);
  2156.         do_always = TRUE;    /* ignore 'mouse' setting next time */
  2157.         return FALSE;
  2158.         }
  2159. #endif
  2160.         /*
  2161.          * The rest is below jump_to_mouse()
  2162.          */
  2163.     }
  2164.  
  2165.     /*
  2166.      * Middle click in insert mode doesn't move the mouse, just insert the
  2167.      * contents of a register.  '.' register is special, can't insert that
  2168.      * with do_put().
  2169.      */
  2170.     else if (State & INSERT)
  2171.     {
  2172.         if (regname == '.')
  2173.         insert_reg(regname, TRUE);
  2174.         else
  2175.         {
  2176. #ifdef FEAT_CLIPBOARD
  2177.         if (clip_star.available && regname == 0)
  2178.             regname = '*';
  2179. #endif
  2180.         if ((State & REPLACE_FLAG) && !yank_register_mline(regname))
  2181.             insert_reg(regname, TRUE);
  2182.         else
  2183.         {
  2184.             do_put(regname, BACKWARD, 1L, fixindent | PUT_CURSEND);
  2185.  
  2186.             /* Repeat it with CTRL-R CTRL-O r or CTRL-R CTRL-P r */
  2187.             AppendCharToRedobuff(Ctrl_R);
  2188.             AppendCharToRedobuff(fixindent ? Ctrl_P : Ctrl_O);
  2189.             AppendCharToRedobuff(regname == 0 ? '"' : regname);
  2190.         }
  2191.         }
  2192.         return FALSE;
  2193.     }
  2194.     else
  2195.         return FALSE;
  2196.     }
  2197.  
  2198.     /* When dragging or button-up stay in the same window. */
  2199.     if (!is_click)
  2200.     jump_flags |= MOUSE_FOCUS | MOUSE_DID_MOVE;
  2201.  
  2202.     start_visual.lnum = 0;
  2203.  
  2204.     /*
  2205.      * When 'mousemodel' is "popup" or "popup_setpos", translate mouse events:
  2206.      * right button up   -> pop-up menu
  2207.      * shift-left button -> right button
  2208.      */
  2209.     if (mouse_model_popup())
  2210.     {
  2211.     if (which_button == MOUSE_RIGHT
  2212.                 && !(mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL)))
  2213.     {
  2214.         /*
  2215.          * NOTE: Ignore right button down and drag mouse events.
  2216.          * Windows only shows the popup menu on the button up event.
  2217.          */
  2218. #if defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_PHOTON)
  2219.         if (!is_click)
  2220.         return FALSE;
  2221. #endif
  2222. #if defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MSWIN)
  2223.         if (is_click || is_drag)
  2224.         return FALSE;
  2225. #endif
  2226. #if defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_GTK) \
  2227.         || defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MSWIN) \
  2228.         || defined(FEAT_GUI_MAC) || defined(FEAT_GUI_PHOTON)
  2229.         if (gui.in_use)
  2230.         {
  2231.         jump_flags = 0;
  2232.         if (STRCMP(p_mousem, "popup_setpos") == 0)
  2233.         {
  2234.             /* First set the cursor position before showing the popup
  2235.              * menu. */
  2236. #ifdef FEAT_VISUAL
  2237.             if (VIsual_active)
  2238.             {
  2239.             pos_T    m_pos;
  2240.  
  2241.             /*
  2242.              * set MOUSE_MAY_STOP_VIS if we are outside the
  2243.              * selection or the current window (might have false
  2244.              * negative here)
  2245.              */
  2246.             if (mouse_row < W_WINROW(curwin)
  2247.                  || mouse_row
  2248.                       > (W_WINROW(curwin) + curwin->w_height))
  2249.                 jump_flags = MOUSE_MAY_STOP_VIS;
  2250.             else if (get_fpos_of_mouse(&m_pos) != IN_BUFFER)
  2251.                 jump_flags = MOUSE_MAY_STOP_VIS;
  2252.             else
  2253.             {
  2254.                 if ((lt(curwin->w_cursor, VIsual)
  2255.                     && (lt(m_pos, curwin->w_cursor)
  2256.                         || lt(VIsual, m_pos)))
  2257.                     || (lt(VIsual, curwin->w_cursor)
  2258.                     && (lt(m_pos, VIsual)
  2259.                         || lt(curwin->w_cursor, m_pos))))
  2260.                 {
  2261.                 jump_flags = MOUSE_MAY_STOP_VIS;
  2262.                 }
  2263.                 else if (VIsual_mode == Ctrl_V)
  2264.                 {
  2265.                 getvcols(curwin, &curwin->w_cursor, &VIsual,
  2266.                              &leftcol, &rightcol);
  2267.                 getvcol(curwin, &m_pos, NULL, &m_pos.col, NULL);
  2268.                 if (m_pos.col < leftcol || m_pos.col > rightcol)
  2269.                     jump_flags = MOUSE_MAY_STOP_VIS;
  2270.                 }
  2271.             }
  2272.             }
  2273.             else
  2274.             jump_flags = MOUSE_MAY_STOP_VIS;
  2275. #endif
  2276.         }
  2277.         if (jump_flags)
  2278.         {
  2279.             jump_flags = jump_to_mouse(jump_flags, NULL, which_button);
  2280.             update_curbuf(
  2281. #ifdef FEAT_VISUAL
  2282.                 VIsual_active ? INVERTED :
  2283. #endif
  2284.                 VALID);
  2285.             setcursor();
  2286.             out_flush();    /* Update before showing popup menu */
  2287.         }
  2288. # ifdef FEAT_MENU
  2289.         gui_show_popupmenu();
  2290. # endif
  2291.         return (jump_flags & CURSOR_MOVED) != 0;
  2292.         }
  2293.         else
  2294.         return FALSE;
  2295. #else
  2296.         return FALSE;
  2297. #endif
  2298.     }
  2299.     if (which_button == MOUSE_LEFT && (mod_mask & MOD_MASK_SHIFT))
  2300.     {
  2301.         which_button = MOUSE_RIGHT;
  2302.         mod_mask &= ~MOD_MASK_SHIFT;
  2303.     }
  2304.     }
  2305.  
  2306. #ifdef FEAT_VISUAL
  2307.     if ((State & (NORMAL | INSERT))
  2308.                 && !(mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL)))
  2309.     {
  2310.     if (which_button == MOUSE_LEFT)
  2311.     {
  2312.         if (is_click)
  2313.         {
  2314.         /* stop Visual mode for a left click in a window, but not when
  2315.          * on a status line */
  2316.         if (VIsual_active)
  2317.             jump_flags |= MOUSE_MAY_STOP_VIS;
  2318.         }
  2319.         else
  2320.         jump_flags |= MOUSE_MAY_VIS;
  2321.     }
  2322.     else if (which_button == MOUSE_RIGHT)
  2323.     {
  2324.         if (is_click && VIsual_active)
  2325.         {
  2326.         /*
  2327.          * Remember the start and end of visual before moving the
  2328.          * cursor.
  2329.          */
  2330.         if (lt(curwin->w_cursor, VIsual))
  2331.         {
  2332.             start_visual = curwin->w_cursor;
  2333.             end_visual = VIsual;
  2334.         }
  2335.         else
  2336.         {
  2337.             start_visual = VIsual;
  2338.             end_visual = curwin->w_cursor;
  2339.         }
  2340.         }
  2341.         jump_flags |= MOUSE_MAY_VIS | MOUSE_FOCUS;
  2342.     }
  2343.     }
  2344. #endif
  2345.  
  2346.     /*
  2347.      * If an operator is pending, ignore all drags and releases until the
  2348.      * next mouse click.
  2349.      */
  2350.     if (!is_drag && oap != NULL && oap->op_type != OP_NOP)
  2351.     {
  2352.     got_click = FALSE;
  2353.     oap->motion_type = MCHAR;
  2354.     }
  2355.  
  2356.     /*
  2357.      * JUMP!
  2358.      */
  2359.     jump_flags = jump_to_mouse(jump_flags,
  2360.             oap == NULL ? NULL : &(oap->inclusive), which_button);
  2361.     moved = (jump_flags & CURSOR_MOVED);
  2362.     in_status_line = (jump_flags & IN_STATUS_LINE);
  2363. #ifdef FEAT_VERTSPLIT
  2364.     in_sep_line = (jump_flags & IN_SEP_LINE);
  2365. #endif
  2366.  
  2367.     /* When jumping to another window, clear a pending operator.  That's a bit
  2368.      * friendlier than beeping and not jumping to that window. */
  2369.     if (curwin != old_curwin && oap != NULL && oap->op_type != OP_NOP)
  2370.     clearop(oap);
  2371.  
  2372. #ifdef FEAT_FOLDING
  2373.     if (mod_mask == 0
  2374.         && !is_drag
  2375.         && (jump_flags & (MOUSE_FOLD_CLOSE | MOUSE_FOLD_OPEN))
  2376.         && which_button == MOUSE_LEFT)
  2377.     {
  2378.     /* open or close a fold at this line */
  2379.     if (jump_flags & MOUSE_FOLD_OPEN)
  2380.         openFold(curwin->w_cursor.lnum, 1L);
  2381.     else
  2382.         closeFold(curwin->w_cursor.lnum, 1L);
  2383.     /* don't move the cursor if still in the same window */
  2384.     if (curwin == old_curwin)
  2385.         curwin->w_cursor = save_cursor;
  2386.     }
  2387. #endif
  2388.  
  2389. #if defined(FEAT_CLIPBOARD) && defined(FEAT_CMDWIN)
  2390.     if ((jump_flags & IN_OTHER_WIN) && !VIsual_active && clip_star.available)
  2391.     {
  2392.     clip_modeless(which_button, is_click, is_drag);
  2393.     return FALSE;
  2394.     }
  2395. #endif
  2396.  
  2397. #ifdef FEAT_VISUAL
  2398.     /* Set global flag that we are extending the Visual area with mouse
  2399.      * dragging; temporarily mimimize 'scrolloff'. */
  2400.     if (VIsual_active && is_drag && p_so)
  2401.     {
  2402.     /* In the very first line, allow scrolling one line */
  2403.     if (mouse_row == 0)
  2404.         mouse_dragging = 2;
  2405.     else
  2406.         mouse_dragging = 1;
  2407.     }
  2408.  
  2409.     /* When dragging the mouse above the window, scroll down. */
  2410.     if (is_drag && mouse_row < 0 && !in_status_line)
  2411.     {
  2412.     scroll_redraw(FALSE, 1L);
  2413.     mouse_row = 0;
  2414.     }
  2415.  
  2416.     if (start_visual.lnum)        /* right click in visual mode */
  2417.     {
  2418.     /*
  2419.      * In Visual-block mode, divide the area in four, pick up the corner
  2420.      * that is in the quarter that the cursor is in.
  2421.      */
  2422.     if (VIsual_mode == Ctrl_V)
  2423.     {
  2424.         getvcols(curwin, &start_visual, &end_visual, &leftcol, &rightcol);
  2425.         if (curwin->w_curswant > (leftcol + rightcol) / 2)
  2426.         end_visual.col = leftcol;
  2427.         else
  2428.         end_visual.col = rightcol;
  2429.         if (curwin->w_cursor.lnum <
  2430.                     (start_visual.lnum + end_visual.lnum) / 2)
  2431.         end_visual.lnum = end_visual.lnum;
  2432.         else
  2433.         end_visual.lnum = start_visual.lnum;
  2434.  
  2435.         /* move VIsual to the right column */
  2436.         start_visual = curwin->w_cursor;        /* save the cursor pos */
  2437.         curwin->w_cursor = end_visual;
  2438.         coladvance(end_visual.col);
  2439.         VIsual = curwin->w_cursor;
  2440.         curwin->w_cursor = start_visual;        /* restore the cursor */
  2441.     }
  2442.     else
  2443.     {
  2444.         /*
  2445.          * If the click is before the start of visual, change the start.
  2446.          * If the click is after the end of visual, change the end.  If
  2447.          * the click is inside the visual, change the closest side.
  2448.          */
  2449.         if (lt(curwin->w_cursor, start_visual))
  2450.         VIsual = end_visual;
  2451.         else if (lt(end_visual, curwin->w_cursor))
  2452.         VIsual = start_visual;
  2453.         else
  2454.         {
  2455.         /* In the same line, compare column number */
  2456.         if (end_visual.lnum == start_visual.lnum)
  2457.         {
  2458.             if (curwin->w_cursor.col - start_visual.col >
  2459.                     end_visual.col - curwin->w_cursor.col)
  2460.             VIsual = start_visual;
  2461.             else
  2462.             VIsual = end_visual;
  2463.         }
  2464.  
  2465.         /* In different lines, compare line number */
  2466.         else
  2467.         {
  2468.             diff = (curwin->w_cursor.lnum - start_visual.lnum) -
  2469.                 (end_visual.lnum - curwin->w_cursor.lnum);
  2470.  
  2471.             if (diff > 0)        /* closest to end */
  2472.             VIsual = start_visual;
  2473.             else if (diff < 0)    /* closest to start */
  2474.             VIsual = end_visual;
  2475.             else            /* in the middle line */
  2476.             {
  2477.             if (curwin->w_cursor.col <
  2478.                     (start_visual.col + end_visual.col) / 2)
  2479.                 VIsual = end_visual;
  2480.             else
  2481.                 VIsual = start_visual;
  2482.             }
  2483.         }
  2484.         }
  2485.     }
  2486.     }
  2487.     /*
  2488.      * If Visual mode started in insert mode, execute "CTRL-O"
  2489.      */
  2490.     else if ((State & INSERT) && VIsual_active)
  2491.     stuffcharReadbuff(Ctrl_O);
  2492. #endif
  2493.  
  2494.     /*
  2495.      * Middle mouse click: Put text before cursor.
  2496.      */
  2497.     if (which_button == MOUSE_MIDDLE)
  2498.     {
  2499. #ifdef FEAT_CLIPBOARD
  2500.     if (clip_star.available && regname == 0)
  2501.         regname = '*';
  2502. #endif
  2503.     if (yank_register_mline(regname))
  2504.     {
  2505.         if (mouse_past_bottom)
  2506.         dir = FORWARD;
  2507.     }
  2508.     else if (mouse_past_eol)
  2509.         dir = FORWARD;
  2510.  
  2511.     if (fixindent)
  2512.     {
  2513.         c1 = (dir == BACKWARD) ? '[' : ']';
  2514.         c2 = 'p';
  2515.     }
  2516.     else
  2517.     {
  2518.         c1 = (dir == FORWARD) ? 'p' : 'P';
  2519.         c2 = NUL;
  2520.     }
  2521.     prep_redo(regname, count, NUL, c1, NUL, c2, NUL);
  2522.  
  2523.     /*
  2524.      * Remember where the paste started, so in edit() Insstart can be set
  2525.      * to this position
  2526.      */
  2527.     if (restart_edit != 0)
  2528.         where_paste_started = curwin->w_cursor;
  2529.     do_put(regname, dir, count, fixindent | PUT_CURSEND);
  2530.     }
  2531.  
  2532. #if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
  2533.     /*
  2534.      * Ctrl-Mouse click or double click in a quickfix window jumps to the
  2535.      * error under the mouse pointer.
  2536.      */
  2537.     else if (((mod_mask & MOD_MASK_CTRL)
  2538.         || (mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK)
  2539.         && bt_quickfix(curbuf))
  2540.     {
  2541.     if (State & INSERT)
  2542.         stuffcharReadbuff(Ctrl_O);
  2543.     stuffReadbuff((char_u *)":.cc\n");
  2544.     got_click = FALSE;        /* ignore drag&release now */
  2545.     }
  2546. #endif
  2547.  
  2548.     /*
  2549.      * Ctrl-Mouse click (or double click in a help window) jumps to the tag
  2550.      * under the mouse pointer.
  2551.      */
  2552.     else if ((mod_mask & MOD_MASK_CTRL) || (curbuf->b_help
  2553.              && (mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK))
  2554.     {
  2555.     if (State & INSERT)
  2556.         stuffcharReadbuff(Ctrl_O);
  2557.     stuffcharReadbuff(Ctrl_RSB);
  2558.     got_click = FALSE;        /* ignore drag&release now */
  2559.     }
  2560.  
  2561.     /*
  2562.      * Shift-Mouse click searches for the next occurrence of the word under
  2563.      * the mouse pointer
  2564.      */
  2565.     else if ((mod_mask & MOD_MASK_SHIFT))
  2566.     {
  2567.     if (State & INSERT
  2568. #ifdef FEAT_VISUAL
  2569.         || (VIsual_active && VIsual_select)
  2570. #endif
  2571.         )
  2572.         stuffcharReadbuff(Ctrl_O);
  2573.     if (which_button == MOUSE_LEFT)
  2574.         stuffcharReadbuff('*');
  2575.     else    /* MOUSE_RIGHT */
  2576.         stuffcharReadbuff('#');
  2577.     }
  2578.  
  2579.     /* Handle double clicks, unless on status line */
  2580.     else if (in_status_line)
  2581.     {
  2582. #ifdef FEAT_MOUSESHAPE
  2583.     if ((is_drag || is_click) && !drag_status_line)
  2584.     {
  2585.         drag_status_line = TRUE;
  2586.         update_mouseshape(-1);
  2587.     }
  2588. #endif
  2589.     }
  2590. #ifdef FEAT_VERTSPLIT
  2591.     else if (in_sep_line)
  2592.     {
  2593. # ifdef FEAT_MOUSESHAPE
  2594.     if ((is_drag || is_click) && !drag_sep_line)
  2595.     {
  2596.         drag_sep_line = TRUE;
  2597.         update_mouseshape(-1);
  2598.     }
  2599. # endif
  2600.     }
  2601. #endif
  2602. #ifdef FEAT_VISUAL
  2603.     else if ((mod_mask & MOD_MASK_MULTI_CLICK) && (State & (NORMAL | INSERT)))
  2604.     {
  2605.     if (is_click || !VIsual_active)
  2606.     {
  2607.         if (VIsual_active)
  2608.         orig_cursor = VIsual;
  2609.         else
  2610.         {
  2611.         check_visual_highlight();
  2612.         VIsual = curwin->w_cursor;
  2613.         orig_cursor = VIsual;
  2614.         VIsual_active = TRUE;
  2615.         VIsual_reselect = TRUE;
  2616.         /* start Select mode if 'selectmode' contains "mouse" */
  2617.         may_start_select('o');
  2618.         setmouse();
  2619.         }
  2620.         if ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK)
  2621.         VIsual_mode = 'v';
  2622.         else if ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_3CLICK)
  2623.         VIsual_mode = 'V';
  2624.         else if ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_4CLICK)
  2625.         VIsual_mode = Ctrl_V;
  2626. #ifdef FEAT_CLIPBOARD
  2627.         /* Make sure the clipboard gets updated.  Needed because start and
  2628.          * end may still be the same, and the selection needs to be owned */
  2629.         clip_star.vmode = NUL;
  2630. #endif
  2631.     }
  2632.     /*
  2633.      * A double click selects a word or a block.
  2634.      */
  2635.     if ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK)
  2636.     {
  2637.         pos_T    *pos = NULL;
  2638.  
  2639.         if (is_click)
  2640.         {
  2641.         /* If the character under the cursor (skipping white space) is
  2642.          * not a word character, try finding a match and select a (),
  2643.          * {}, [], #if/#endif, etc. block. */
  2644.         end_visual = curwin->w_cursor;
  2645.         while (vim_iswhite(gchar_pos(&end_visual)))
  2646.             inc(&end_visual);
  2647.         if (oap != NULL)
  2648.             oap->motion_type = MCHAR;
  2649.         if (oap != NULL
  2650.             && VIsual_mode == 'v'
  2651.             && !vim_isIDc(gchar_pos(&end_visual))
  2652.             && equal(curwin->w_cursor, VIsual)
  2653.             && (pos = findmatch(oap, NUL)) != NULL)
  2654.         {
  2655.             curwin->w_cursor = *pos;
  2656.             if (oap->motion_type == MLINE)
  2657.             VIsual_mode = 'V';
  2658.             else if (*p_sel == 'e')
  2659.             {
  2660.             if (lt(curwin->w_cursor, VIsual))
  2661.                 ++VIsual.col;
  2662.             else
  2663.                 ++curwin->w_cursor.col;
  2664.             }
  2665.         }
  2666.         }
  2667.  
  2668.         if (pos == NULL && (is_click || is_drag))
  2669.         {
  2670.         /* When not found a match or when dragging: extend to include
  2671.          * a word. */
  2672.         if (lt(curwin->w_cursor, orig_cursor))
  2673.         {
  2674.             find_start_of_word(&curwin->w_cursor);
  2675.             find_end_of_word(&VIsual);
  2676.         }
  2677.         else
  2678.         {
  2679.             find_start_of_word(&VIsual);
  2680.             find_end_of_word(&curwin->w_cursor);
  2681.         }
  2682.         }
  2683.         curwin->w_set_curswant = TRUE;
  2684.     }
  2685.     if (is_click)
  2686.         redraw_curbuf_later(INVERTED);    /* update the inversion */
  2687.     }
  2688.     else if (VIsual_active && !old_active)
  2689.     VIsual_mode = 'v';
  2690.  
  2691.     /* If Visual mode changed show it later. */
  2692.     if (p_smd && (VIsual_active != old_active || VIsual_mode != old_mode))
  2693.     redraw_cmdline = TRUE;
  2694. #endif
  2695.  
  2696.     return moved;
  2697. }
  2698.  
  2699. #ifdef FEAT_VISUAL
  2700. /*
  2701.  * Move "pos" back to the start of the word it's in.
  2702.  */
  2703.     static void
  2704. find_start_of_word(pos)
  2705.     pos_T    *pos;
  2706. {
  2707.     char_u    *line;
  2708.     int        cclass;
  2709.     int        col;
  2710.  
  2711.     line = ml_get(pos->lnum);
  2712.     cclass = get_mouse_class(line + pos->col);
  2713.  
  2714.     while (pos->col > 0)
  2715.     {
  2716.     col = pos->col - 1;
  2717. #ifdef FEAT_MBYTE
  2718.     col -= (*mb_head_off)(line, line + col);
  2719. #endif
  2720.     if (get_mouse_class(line + col) != cclass)
  2721.         break;
  2722.     pos->col = col;
  2723.     }
  2724. }
  2725.  
  2726. /*
  2727.  * Move "pos" forward to the end of the word it's in.
  2728.  * When 'selection' is "exclusive", the position is just after the word.
  2729.  */
  2730.     static void
  2731. find_end_of_word(pos)
  2732.     pos_T    *pos;
  2733. {
  2734.     char_u    *line;
  2735.     int        cclass;
  2736.     int        col;
  2737.  
  2738.     line = ml_get(pos->lnum);
  2739.     if (*p_sel == 'e' && pos->col > 0)
  2740.     {
  2741.     --pos->col;
  2742. #ifdef FEAT_MBYTE
  2743.     pos->col -= (*mb_head_off)(line, line + pos->col);
  2744. #endif
  2745.     }
  2746.     cclass = get_mouse_class(line + pos->col);
  2747.     while (line[pos->col] != NUL)
  2748.     {
  2749. #ifdef FEAT_MBYTE
  2750.     col = pos->col + (*mb_ptr2len_check)(line + pos->col);
  2751. #else
  2752.     col = pos->col + 1;
  2753. #endif
  2754.     if (get_mouse_class(line + col) != cclass)
  2755.     {
  2756.         if (*p_sel == 'e')
  2757.         pos->col = col;
  2758.         break;
  2759.     }
  2760.     pos->col = col;
  2761.     }
  2762. }
  2763.  
  2764. /*
  2765.  * Get class of a character for selection: same class means same word.
  2766.  * 0: blank
  2767.  * 1: punctuation groups
  2768.  * 2: normal word character
  2769.  * >2: multi-byte word character.
  2770.  */
  2771.     static int
  2772. get_mouse_class(p)
  2773.     char_u    *p;
  2774. {
  2775.     int        c;
  2776.  
  2777. #ifdef FEAT_MBYTE
  2778.     if (has_mbyte && MB_BYTE2LEN(p[0]) > 1)
  2779.     return mb_get_class(p);
  2780. #endif
  2781.  
  2782.     c = *p;
  2783.     if (c == ' ' || c == '\t')
  2784.     return 0;
  2785.  
  2786.     if (vim_isIDc(c))
  2787.     return 1;
  2788.  
  2789.     /*
  2790.      * There are a few special cases where we want certain combinations of
  2791.      * characters to be considered as a single word.  These are things like
  2792.      * "->", "/ *", "*=", "+=", "&=", "<=", ">=", "!=" etc.  Otherwise, each
  2793.      * character is in it's own class.
  2794.      */
  2795.     if (c != NUL && vim_strchr((char_u *)"-+*/%<>&|^!=", c) != NULL)
  2796.     return 2;
  2797.     return c;
  2798. }
  2799. #endif /* FEAT_VISUAL */
  2800. #endif /* FEAT_MOUSE */
  2801.  
  2802. #if defined(FEAT_VISUAL) || defined(PROTO)
  2803. /*
  2804.  * Check if  highlighting for visual mode is possible, give a warning message
  2805.  * if not.
  2806.  */
  2807.     void
  2808. check_visual_highlight()
  2809. {
  2810.     static int        did_check = FALSE;
  2811.  
  2812.     if (!did_check && hl_attr(HLF_V) == 0)
  2813.     MSG(_("Warning: terminal cannot highlight"));
  2814.     did_check = TRUE;
  2815. }
  2816.  
  2817. /*
  2818.  * End visual mode.
  2819.  * This function should ALWAYS be called to end Visual mode, except from
  2820.  * do_pending_operator().
  2821.  */
  2822.     void
  2823. end_visual_mode()
  2824. {
  2825. #ifdef FEAT_CLIPBOARD
  2826.     /*
  2827.      * If we are using the clipboard, then remember what was selected in case
  2828.      * we need to paste it somewhere while we still own the selection.
  2829.      * Only do this when the clipboard is already owned.  Don't want to grab
  2830.      * the selection when hitting ESC.
  2831.      */
  2832.     if (clip_star.available && clip_star.owned)
  2833.     clip_auto_select();
  2834. #endif
  2835.  
  2836.     VIsual_active = FALSE;
  2837. #ifdef FEAT_MOUSE
  2838.     setmouse();
  2839.     mouse_dragging = 0;
  2840. #endif
  2841.  
  2842.     /* Save the current VIsual area for '< and '> marks, and "gv" */
  2843.     curbuf->b_visual_mode = VIsual_mode;
  2844.     curbuf->b_visual_start = VIsual;
  2845.     curbuf->b_visual_end = curwin->w_cursor;
  2846.     curbuf->b_visual_curswant = curwin->w_curswant;
  2847. #ifdef FEAT_VIRTUALEDIT
  2848.     if (!virtual_active())
  2849.     curwin->w_cursor.coladd = 0;
  2850. #endif
  2851.  
  2852.     if (p_smd)
  2853.     clear_cmdline = TRUE;        /* unshow visual mode later */
  2854. #ifdef FEAT_CMDL_INFO
  2855.     else
  2856.     clear_showcmd();
  2857. #endif
  2858.  
  2859.     /* Don't leave the cursor past the end of the line */
  2860.     if (curwin->w_cursor.col > 0 && *ml_get_cursor() == NUL)
  2861.     --curwin->w_cursor.col;
  2862. }
  2863.  
  2864. /*
  2865.  * Reset VIsual_active and VIsual_reselect.
  2866.  */
  2867.     void
  2868. reset_VIsual_and_resel()
  2869. {
  2870.     if (VIsual_active)
  2871.     {
  2872.     end_visual_mode();
  2873.     redraw_curbuf_later(INVERTED);    /* delete the inversion later */
  2874.     }
  2875.     VIsual_reselect = FALSE;
  2876. }
  2877.  
  2878. /*
  2879.  * Reset VIsual_active and VIsual_reselect if it's set.
  2880.  */
  2881.     void
  2882. reset_VIsual()
  2883. {
  2884.     if (VIsual_active)
  2885.     {
  2886.     end_visual_mode();
  2887.     redraw_curbuf_later(INVERTED);    /* delete the inversion later */
  2888.     VIsual_reselect = FALSE;
  2889.     }
  2890. }
  2891. #endif /* FEAT_VISUAL */
  2892.  
  2893. /*
  2894.  * Find the identifier under or to the right of the cursor.
  2895.  * "find_type" can have one of three values:
  2896.  * FIND_IDENT:   find an identifier (keyword)
  2897.  * FIND_STRING:  find any non-white string
  2898.  * FIND_IDENT + FIND_STRING: find any non-white string, identifier preferred.
  2899.  *
  2900.  * There are three steps:
  2901.  * 1. Search forward for the start of an identifier/string.  Doesn't move if
  2902.  *    already on one.
  2903.  * 2. Search backward for the start of this identifier/string.
  2904.  *    This doesn't match the real Vi but I like it a little better and it
  2905.  *    shouldn't bother anyone.
  2906.  * 3. Search forward to the end of this identifier/string.
  2907.  *    When FIND_IDENT isn't defined, we backup until a blank.
  2908.  *
  2909.  * Returns the length of the string, or zero if no string is found.
  2910.  * If a string is found, a pointer to the string is put in "*string".  This
  2911.  * string is not always NUL terminated.
  2912.  */
  2913.     int
  2914. find_ident_under_cursor(string, find_type)
  2915.     char_u    **string;
  2916.     int        find_type;
  2917. {
  2918.     char_u    *ptr;
  2919.     int        col = 0;        /* init to shut up GCC */
  2920.     int        i;
  2921. #ifdef FEAT_MBYTE
  2922.     int        this_class = 0;
  2923.     int        prev_class;
  2924.     int        prevcol;
  2925. #endif
  2926.  
  2927.     /*
  2928.      * if i == 0: try to find an identifier
  2929.      * if i == 1: try to find any non-white string
  2930.      */
  2931.     ptr = ml_get_curline();
  2932.     for (i = (find_type & FIND_IDENT) ? 0 : 1;    i < 2; ++i)
  2933.     {
  2934.     /*
  2935.      * 1. skip to start of identifier/string
  2936.      */
  2937.     col = curwin->w_cursor.col;
  2938. #ifdef FEAT_MBYTE
  2939.     if (has_mbyte)
  2940.     {
  2941.         while (ptr[col] != NUL)
  2942.         {
  2943.         this_class = mb_get_class(ptr + col);
  2944.         if (this_class != 0 && (i == 1 || this_class != 1))
  2945.             break;
  2946.         col += (*mb_ptr2len_check)(ptr + col);
  2947.         }
  2948.     }
  2949.     else
  2950. #endif
  2951.         while (ptr[col] != NUL && (i == 0
  2952.             ? !vim_iswordc(ptr[col]) : vim_iswhite(ptr[col])))
  2953.         ++col;
  2954.  
  2955.     /*
  2956.      * 2. Back up to start of identifier/string.
  2957.      */
  2958. #ifdef FEAT_MBYTE
  2959.     if (has_mbyte)
  2960.     {
  2961.         /* Remember class of character under cursor. */
  2962.         this_class = mb_get_class(ptr + col);
  2963.         while (col > 0)
  2964.         {
  2965.         prevcol = col - 1 - (*mb_head_off)(ptr, ptr + col - 1);
  2966.         prev_class = mb_get_class(ptr + prevcol);
  2967.         if (this_class != prev_class
  2968.             && (i == 0
  2969.                 || prev_class == 0
  2970.                 || (find_type & FIND_IDENT)))
  2971.             break;
  2972.         col = prevcol;
  2973.         }
  2974.  
  2975.         /* If we don't want just any old string, or we've found an
  2976.          * identifier, stop searching. */
  2977.         if (this_class > 2)
  2978.         this_class = 2;
  2979.         if (!(find_type & FIND_STRING) || this_class == 2)
  2980.         break;
  2981.     }
  2982.     else
  2983. #endif
  2984.     {
  2985.         while (col > 0 && (i == 0 ? vim_iswordc(ptr[col - 1])
  2986.             : (!vim_iswhite(ptr[col - 1])
  2987.                 && (!(find_type & FIND_IDENT)
  2988.                 || !vim_iswordc(ptr[col - 1])))))
  2989.         --col;
  2990.  
  2991.         /* If we don't want just any old string, or we've found an
  2992.          * identifier, stop searching. */
  2993.         if (!(find_type & FIND_STRING) || vim_iswordc(ptr[col]))
  2994.         break;
  2995.     }
  2996.     }
  2997.  
  2998.     if (ptr[col] == NUL || (i == 0 && (
  2999. #ifdef FEAT_MBYTE
  3000.         has_mbyte ? this_class != 2 :
  3001. #endif
  3002.         !vim_iswordc(ptr[col]))))
  3003.     {
  3004.     /*
  3005.      * didn't find an identifier or string
  3006.      */
  3007.     if (find_type & FIND_STRING)
  3008.         EMSG(_("E348: No string under cursor"));
  3009.     else
  3010.         EMSG(_("E349: No identifier under cursor"));
  3011.     return 0;
  3012.     }
  3013.     ptr += col;
  3014.     *string = ptr;
  3015.  
  3016.     /*
  3017.      * 3. Find the end if the identifier/string.
  3018.      */
  3019.     col = 0;
  3020. #ifdef FEAT_MBYTE
  3021.     if (has_mbyte)
  3022.     {
  3023.     /* Search for point of changing multibyte character class. */
  3024.     this_class = mb_get_class(ptr);
  3025.     while (ptr[col] != NUL
  3026.         && i == 0 ? mb_get_class(ptr + col) == this_class
  3027.               : mb_get_class(ptr + col) != 0)
  3028.         col += (*mb_ptr2len_check)(ptr + col);
  3029.     }
  3030.     else
  3031. #endif
  3032.     while (i == 0 ? vim_iswordc(*ptr) : (*ptr != NUL && !vim_iswhite(*ptr)))
  3033.     {
  3034.         ++ptr;
  3035.         ++col;
  3036.     }
  3037.  
  3038.     return col;
  3039. }
  3040.  
  3041. /*
  3042.  * Prepare for redo of a normal command.
  3043.  */
  3044.     static void
  3045. prep_redo_cmd(cap)
  3046.     cmdarg_T  *cap;
  3047. {
  3048.     prep_redo(cap->oap->regname, cap->count0,
  3049.                      NUL, cap->cmdchar, NUL, NUL, cap->nchar);
  3050. }
  3051.  
  3052. /*
  3053.  * Prepare for redo of any command.
  3054.  * Note that only the last argument can be a multi-byte char.
  3055.  */
  3056.     static void
  3057. prep_redo(regname, num, cmd1, cmd2, cmd3, cmd4, cmd5)
  3058.     int        regname;
  3059.     long    num;
  3060.     int        cmd1;
  3061.     int        cmd2;
  3062.     int        cmd3;
  3063.     int        cmd4;
  3064.     int        cmd5;
  3065. {
  3066.     ResetRedobuff();
  3067.     if (regname != 0)    /* yank from specified buffer */
  3068.     {
  3069.     AppendCharToRedobuff('"');
  3070.     AppendCharToRedobuff(regname);
  3071.     }
  3072.     if (num)
  3073.     AppendNumberToRedobuff(num);
  3074.  
  3075.     if (cmd1 != NUL)
  3076.     AppendCharToRedobuff(cmd1);
  3077.     if (cmd2 != NUL)
  3078.     AppendCharToRedobuff(cmd2);
  3079.     if (cmd3 != NUL)
  3080.     AppendCharToRedobuff(cmd3);
  3081.     if (cmd4 != NUL)
  3082.     AppendCharToRedobuff(cmd4);
  3083.     if (cmd5 != NUL)
  3084.     AppendCharToRedobuff(cmd5);
  3085. }
  3086.  
  3087. /*
  3088.  * check for operator active and clear it
  3089.  *
  3090.  * return TRUE if operator was active
  3091.  */
  3092.     static int
  3093. checkclearop(oap)
  3094.     oparg_T    *oap;
  3095. {
  3096.     if (oap->op_type == OP_NOP)
  3097.     return FALSE;
  3098.     clearopbeep(oap);
  3099.     return TRUE;
  3100. }
  3101.  
  3102. /*
  3103.  * check for operator or Visual active and clear it
  3104.  *
  3105.  * return TRUE if operator was active
  3106.  */
  3107.     static int
  3108. checkclearopq(oap)
  3109.     oparg_T    *oap;
  3110. {
  3111.     if (oap->op_type == OP_NOP
  3112. #ifdef FEAT_VISUAL
  3113.         && !VIsual_active
  3114. #endif
  3115.         )
  3116.     return FALSE;
  3117.     clearopbeep(oap);
  3118.     return TRUE;
  3119. }
  3120.  
  3121.     static void
  3122. clearop(oap)
  3123.     oparg_T    *oap;
  3124. {
  3125.     oap->op_type = OP_NOP;
  3126.     oap->regname = 0;
  3127.     oap->motion_force = NUL;
  3128.     oap->use_reg_one = FALSE;
  3129. }
  3130.  
  3131.     static void
  3132. clearopbeep(oap)
  3133.     oparg_T    *oap;
  3134. {
  3135.     clearop(oap);
  3136.     beep_flush();
  3137. }
  3138.  
  3139. #ifdef FEAT_VISUAL
  3140. /*
  3141.  * Remove the shift modifier from a special key.
  3142.  */
  3143.     static void
  3144. unshift_special(cap)
  3145.     cmdarg_T    *cap;
  3146. {
  3147.     switch (cap->cmdchar)
  3148.     {
  3149.     case K_S_RIGHT:    cap->cmdchar = K_RIGHT; break;
  3150.     case K_S_LEFT:    cap->cmdchar = K_LEFT; break;
  3151.     case K_S_UP:    cap->cmdchar = K_UP; break;
  3152.     case K_S_DOWN:    cap->cmdchar = K_DOWN; break;
  3153.     case K_S_HOME:    cap->cmdchar = K_HOME; break;
  3154.     case K_S_END:    cap->cmdchar = K_END; break;
  3155.     }
  3156.     cap->cmdchar = simplify_key(cap->cmdchar, &mod_mask);
  3157. }
  3158. #endif
  3159.  
  3160. #if defined(FEAT_CMDL_INFO) || defined(PROTO)
  3161. /*
  3162.  * Routines for displaying a partly typed command
  3163.  */
  3164.  
  3165. #ifdef FEAT_VISUAL    /* need room for size of Visual area */
  3166. # define SHOWCMD_BUFLEN SHOWCMD_COLS + 1 + 30
  3167. #else
  3168. # define SHOWCMD_BUFLEN SHOWCMD_COLS + 1
  3169. #endif
  3170. static char_u    showcmd_buf[SHOWCMD_BUFLEN];
  3171. static char_u    old_showcmd_buf[SHOWCMD_BUFLEN];  /* For push_showcmd() */
  3172. static int    showcmd_is_clear = TRUE;
  3173. static int    showcmd_visual = FALSE;
  3174.  
  3175. static void display_showcmd __ARGS((void));
  3176.  
  3177.     void
  3178. clear_showcmd()
  3179. {
  3180.     if (!p_sc)
  3181.     return;
  3182.  
  3183. #ifdef FEAT_VISUAL
  3184.     if (VIsual_active)
  3185.     {
  3186.     int    i = lt(VIsual, curwin->w_cursor);
  3187.     long    lines;
  3188.     colnr_T    leftcol, rightcol;
  3189.  
  3190.     /* Show the size of the Visual area. */
  3191.     if (i)
  3192.         lines = curwin->w_cursor.lnum - VIsual.lnum + 1;
  3193.     else
  3194.         lines = VIsual.lnum - curwin->w_cursor.lnum + 1;
  3195.     if (VIsual_mode == Ctrl_V)
  3196.     {
  3197.         getvcols(curwin, &curwin->w_cursor, &VIsual, &leftcol, &rightcol);
  3198.         sprintf((char *)showcmd_buf, "%ldx%ld", lines,
  3199.                           (long)(rightcol - leftcol + 1));
  3200.     }
  3201.     else if (VIsual_mode == 'V' || VIsual.lnum != curwin->w_cursor.lnum)
  3202.         sprintf((char *)showcmd_buf, "%ld", lines);
  3203.     else
  3204.         sprintf((char *)showcmd_buf, "%ld", (long)(i
  3205.             ? curwin->w_cursor.col - VIsual.col
  3206.             : VIsual.col - curwin->w_cursor.col) + (*p_sel != 'e'));
  3207.     showcmd_buf[SHOWCMD_COLS] = NUL;    /* truncate */
  3208.     showcmd_visual = TRUE;
  3209.     }
  3210.     else
  3211. #endif
  3212.     {
  3213.     showcmd_buf[0] = NUL;
  3214.     showcmd_visual = FALSE;
  3215.  
  3216.     /* Don't actually display something if there is nothing to clear. */
  3217.     if (showcmd_is_clear)
  3218.         return;
  3219.     }
  3220.  
  3221.     display_showcmd();
  3222. }
  3223.  
  3224. /*
  3225.  * Add 'c' to string of shown command chars.
  3226.  * Return TRUE if output has been written (and setcursor() has been called).
  3227.  */
  3228.     int
  3229. add_to_showcmd(c)
  3230.     int        c;
  3231. {
  3232.     char_u    *p;
  3233.     int        old_len;
  3234.     int        extra_len;
  3235.     int        overflow;
  3236. #if defined(FEAT_MOUSE)
  3237.     int        i;
  3238.     static int    ignore[] =
  3239.     {
  3240. #ifdef FEAT_GUI
  3241.     K_VER_SCROLLBAR, K_HOR_SCROLLBAR,
  3242.     K_LEFTMOUSE_NM, K_LEFTRELEASE_NM,
  3243. #endif
  3244.     K_IGNORE,
  3245.     K_LEFTMOUSE, K_LEFTDRAG, K_LEFTRELEASE,
  3246.     K_MIDDLEMOUSE, K_MIDDLEDRAG, K_MIDDLERELEASE,
  3247.     K_RIGHTMOUSE, K_RIGHTDRAG, K_RIGHTRELEASE,
  3248.     K_MOUSEDOWN, K_MOUSEUP,
  3249.     0
  3250.     };
  3251. #endif
  3252.  
  3253.     if (!p_sc)
  3254.     return FALSE;
  3255.  
  3256.     if (showcmd_visual)
  3257.     {
  3258.     showcmd_buf[0] = NUL;
  3259.     showcmd_visual = FALSE;
  3260.     }
  3261.  
  3262. #if defined(FEAT_MOUSE)
  3263.     /* Ignore keys that are scrollbar updates and mouse clicks */
  3264.     if (IS_SPECIAL(c))
  3265.     for (i = 0; ignore[i] != 0; ++i)
  3266.         if (ignore[i] == c)
  3267.         return FALSE;
  3268. #endif
  3269.  
  3270.     p = transchar(c);
  3271.     old_len = (int)STRLEN(showcmd_buf);
  3272.     extra_len = (int)STRLEN(p);
  3273.     overflow = old_len + extra_len - SHOWCMD_COLS;
  3274.     if (overflow > 0)
  3275.     STRCPY(showcmd_buf, showcmd_buf + overflow);
  3276.     STRCAT(showcmd_buf, p);
  3277.  
  3278.     if (char_avail())
  3279.     return FALSE;
  3280.  
  3281.     display_showcmd();
  3282.  
  3283.     return TRUE;
  3284. }
  3285.  
  3286.     void
  3287. add_to_showcmd_c(c)
  3288.     int        c;
  3289. {
  3290.     if (!add_to_showcmd(c))
  3291.     setcursor();
  3292. }
  3293.  
  3294. /*
  3295.  * Delete 'len' characters from the end of the shown command.
  3296.  */
  3297.     static void
  3298. del_from_showcmd(len)
  3299.     int        len;
  3300. {
  3301.     int        old_len;
  3302.  
  3303.     if (!p_sc)
  3304.     return;
  3305.  
  3306.     old_len = (int)STRLEN(showcmd_buf);
  3307.     if (len > old_len)
  3308.     len = old_len;
  3309.     showcmd_buf[old_len - len] = NUL;
  3310.  
  3311.     if (!char_avail())
  3312.     display_showcmd();
  3313. }
  3314.  
  3315.     void
  3316. push_showcmd()
  3317. {
  3318.     if (p_sc)
  3319.     STRCPY(old_showcmd_buf, showcmd_buf);
  3320. }
  3321.  
  3322.     void
  3323. pop_showcmd()
  3324. {
  3325.     if (!p_sc)
  3326.     return;
  3327.  
  3328.     STRCPY(showcmd_buf, old_showcmd_buf);
  3329.  
  3330.     display_showcmd();
  3331. }
  3332.  
  3333.     static void
  3334. display_showcmd()
  3335. {
  3336.     int        len;
  3337.  
  3338.     cursor_off();
  3339.  
  3340.     len = (int)STRLEN(showcmd_buf);
  3341.     if (len == 0)
  3342.     showcmd_is_clear = TRUE;
  3343.     else
  3344.     {
  3345.     screen_puts(showcmd_buf, (int)Rows - 1, sc_col, 0);
  3346.     showcmd_is_clear = FALSE;
  3347.     }
  3348.  
  3349.     /*
  3350.      * clear the rest of an old message by outputing up to SHOWCMD_COLS spaces
  3351.      */
  3352.     screen_puts((char_u *)"          " + len, (int)Rows - 1, sc_col + len, 0);
  3353.  
  3354.     setcursor();        /* put cursor back where it belongs */
  3355. }
  3356. #endif
  3357.  
  3358. #ifdef FEAT_SCROLLBIND
  3359. /*
  3360.  * When "check" is FALSE, prepare for commands that scroll the window.
  3361.  * When "check" is TRUE, take care of scroll-binding after the window has
  3362.  * scrolled.  Called from normal_cmd() and edit().
  3363.  */
  3364.     void
  3365. do_check_scrollbind(check)
  3366.     int        check;
  3367. {
  3368.     static win_T    *old_curwin = NULL;
  3369.     static linenr_T    old_topline = 0;
  3370. #ifdef FEAT_DIFF
  3371.     static int        old_topfill = 0;
  3372. #endif
  3373.     static buf_T    *old_buf = NULL;
  3374.     static colnr_T    old_leftcol = 0;
  3375.  
  3376.     if (check && curwin->w_p_scb)
  3377.     {
  3378.     /* If a ":syncbind" command was just used, don't scroll, only reset
  3379.      * the values. */
  3380.     if (did_syncbind)
  3381.         did_syncbind = FALSE;
  3382.     else if (curwin == old_curwin)
  3383.     {
  3384.         /*
  3385.          * Synchronize other windows, as necessary according to
  3386.          * 'scrollbind'.  Don't do this after an ":edit" command, except
  3387.          * when 'diff' is set.
  3388.          */
  3389.         if ((curwin->w_buffer == old_buf
  3390. #ifdef FEAT_DIFF
  3391.             || curwin->w_p_diff
  3392. #endif
  3393.         )
  3394.         && (curwin->w_topline != old_topline
  3395. #ifdef FEAT_DIFF
  3396.             || curwin->w_topfill != old_topfill
  3397. #endif
  3398.             || curwin->w_leftcol != old_leftcol))
  3399.         {
  3400.         check_scrollbind(curwin->w_topline - old_topline,
  3401.             (long)(curwin->w_leftcol - old_leftcol));
  3402.         }
  3403.     }
  3404.     else if (vim_strchr(p_sbo, 'j')) /* jump flag set in 'scrollopt' */
  3405.     {
  3406.         /*
  3407.          * When switching between windows, make sure that the relative
  3408.          * vertical offset is valid for the new window.  The relative
  3409.          * offset is invalid whenever another 'scrollbind' window has
  3410.          * scrolled to a point that would force the current window to
  3411.          * scroll past the beginning or end of its buffer.  When the
  3412.          * resync is performed, some of the other 'scrollbind' windows may
  3413.          * need to jump so that the current window's relative position is
  3414.          * visible on-screen.
  3415.          */
  3416.         check_scrollbind(curwin->w_topline - curwin->w_scbind_pos, 0L);
  3417.     }
  3418.     curwin->w_scbind_pos = curwin->w_topline;
  3419.     }
  3420.  
  3421.     old_curwin = curwin;
  3422.     old_topline = curwin->w_topline;
  3423. #ifdef FEAT_DIFF
  3424.     old_topfill = curwin->w_topfill;
  3425. #endif
  3426.     old_buf = curwin->w_buffer;
  3427.     old_leftcol = curwin->w_leftcol;
  3428. }
  3429.  
  3430. /*
  3431.  * Synchronize any windows that have "scrollbind" set, based on the
  3432.  * number of rows by which the current window has changed
  3433.  * (1998-11-02 16:21:01  R. Edward Ralston <eralston@computer.org>)
  3434.  */
  3435.     void
  3436. check_scrollbind(topline_diff, leftcol_diff)
  3437.     linenr_T    topline_diff;
  3438.     long    leftcol_diff;
  3439. {
  3440.     int        want_ver;
  3441.     int        want_hor;
  3442.     win_T    *old_curwin = curwin;
  3443.     buf_T    *old_curbuf = curbuf;
  3444. #ifdef FEAT_VISUAL
  3445.     int        old_VIsual_select = VIsual_select;
  3446.     int        old_VIsual_active = VIsual_active;
  3447. #endif
  3448.     colnr_T    tgt_leftcol = curwin->w_leftcol;
  3449.     long    topline;
  3450.     long    y;
  3451.  
  3452.     /*
  3453.      * check 'scrollopt' string for vertical and horizontal scroll options
  3454.      */
  3455.     want_ver = (vim_strchr(p_sbo, 'v') && topline_diff != 0);
  3456. #ifdef FEAT_DIFF
  3457.     want_ver |= old_curwin->w_p_diff;
  3458. #endif
  3459.     want_hor = (vim_strchr(p_sbo, 'h') && (leftcol_diff || topline_diff != 0));
  3460.  
  3461.     /*
  3462.      * loop through the scrollbound windows and scroll accordingly
  3463.      */
  3464. #ifdef FEAT_VISUAL
  3465.     VIsual_select = VIsual_active = 0;
  3466. #endif
  3467.     for (curwin = firstwin; curwin; curwin = curwin->w_next)
  3468.     {
  3469.     curbuf = curwin->w_buffer;
  3470.     /* skip original window  and windows with 'noscrollbind' */
  3471.     if (curwin != old_curwin && curwin->w_p_scb)
  3472.     {
  3473.         /*
  3474.          * do the vertical scroll
  3475.          */
  3476.         if (want_ver)
  3477.         {
  3478. #ifdef FEAT_DIFF
  3479.         if (old_curwin->w_p_diff && curwin->w_p_diff)
  3480.         {
  3481.             diff_set_topline(old_curwin, curwin);
  3482.         }
  3483.         else
  3484. #endif
  3485.         {
  3486.             curwin->w_scbind_pos += topline_diff;
  3487.             topline = curwin->w_scbind_pos;
  3488.             if (topline > curbuf->b_ml.ml_line_count - p_so)
  3489.             topline = curbuf->b_ml.ml_line_count - p_so;
  3490.             if (topline < 1)
  3491.             topline = 1;
  3492.  
  3493.             y = topline - curwin->w_topline;
  3494.             if (y > 0)
  3495.             scrollup(y, FALSE);
  3496.             else
  3497.             scrolldown(-y, FALSE);
  3498.         }
  3499.  
  3500.         redraw_later(VALID);
  3501.         cursor_correct();
  3502. #ifdef FEAT_WINDOWS
  3503.         curwin->w_redr_status = TRUE;
  3504. #endif
  3505.         }
  3506.  
  3507.         /*
  3508.          * do the horizontal scroll
  3509.          */
  3510.         if (want_hor && curwin->w_leftcol != tgt_leftcol)
  3511.         {
  3512.         curwin->w_leftcol = tgt_leftcol;
  3513.         leftcol_changed();
  3514.         }
  3515.     }
  3516.     }
  3517.  
  3518.     /*
  3519.      * reset current-window
  3520.      */
  3521. #ifdef FEAT_VISUAL
  3522.     VIsual_select = old_VIsual_select;
  3523.     VIsual_active = old_VIsual_active;
  3524. #endif
  3525.     curwin = old_curwin;
  3526.     curbuf = old_curbuf;
  3527. }
  3528. #endif /* #ifdef FEAT_SCROLLBIND */
  3529.  
  3530. /*
  3531.  * Command character that's ignored.
  3532.  * Used for CTRL-Q and CTRL-S to avoid problems with terminals that use
  3533.  * xon/xoff
  3534.  */
  3535. /*ARGSUSED */
  3536.     static void
  3537. nv_ignore(cap)
  3538.     cmdarg_T    *cap;
  3539. {
  3540. }
  3541.  
  3542. /*
  3543.  * Command character doesn't exist.
  3544.  */
  3545.     static void
  3546. nv_error(cap)
  3547.     cmdarg_T    *cap;
  3548. {
  3549.     clearopbeep(cap->oap);
  3550. }
  3551.  
  3552. /*
  3553.  * <Help> and <F1> commands.
  3554.  */
  3555.     static void
  3556. nv_help(cap)
  3557.     cmdarg_T    *cap;
  3558. {
  3559.     if (!checkclearopq(cap->oap))
  3560.     ex_help(NULL);
  3561. }
  3562.  
  3563. /*
  3564.  * CTRL-A and CTRL-X: Add or subtract from letter or number under cursor.
  3565.  */
  3566.     static void
  3567. nv_addsub(cap)
  3568.     cmdarg_T    *cap;
  3569. {
  3570.     if (!checkclearopq(cap->oap)
  3571.         && do_addsub((int)cap->cmdchar, cap->count1) == OK)
  3572.     prep_redo_cmd(cap);
  3573. }
  3574.  
  3575. /*
  3576.  * CTRL-F, CTRL-B, etc: Scroll page up or down.
  3577.  */
  3578.     static void
  3579. nv_page(cap)
  3580.     cmdarg_T    *cap;
  3581. {
  3582.     if (!checkclearop(cap->oap))
  3583.     (void)onepage(cap->arg, cap->count1);
  3584. }
  3585.  
  3586. /*
  3587.  * Implementation of "gd" and "gD" command.
  3588.  */
  3589.     static void
  3590. nv_gd(oap, nchar)
  3591.     oparg_T   *oap;
  3592.     int        nchar;
  3593. {
  3594.     int        len;
  3595.     char_u    *pat;
  3596.     pos_T    old_pos;
  3597.     int        t;
  3598.     int        save_p_ws;
  3599.     int        save_p_scs;
  3600.     char_u    *ptr;
  3601.  
  3602.     if ((len = find_ident_under_cursor(&ptr, FIND_IDENT)) == 0 ||
  3603.                            (pat = alloc(len + 5)) == NULL)
  3604.     {
  3605.     clearopbeep(oap);
  3606.     return;
  3607.     }
  3608.     sprintf((char *)pat, vim_iswordp(ptr) ? "\\<%.*s\\>" : "%.*s", len, ptr);
  3609.     old_pos = curwin->w_cursor;
  3610.     save_p_ws = p_ws;
  3611.     save_p_scs = p_scs;
  3612.     p_ws = FALSE;    /* don't wrap around end of file now */
  3613.     p_scs = FALSE;    /* don't switch ignorecase off now */
  3614.  
  3615.     /*
  3616.      * With "gD" go to line 1.
  3617.      * With "gd" Search back for the start of the current function, then go
  3618.      * back until a blank line.  If this fails go to line 1.
  3619.      */
  3620.     if (nchar == 'D' || !findpar(oap, BACKWARD, 1L, '{', FALSE))
  3621.     {
  3622.     setpcmark();            /* Set in findpar() otherwise */
  3623.     curwin->w_cursor.lnum = 1;
  3624.     }
  3625.     else
  3626.     {
  3627.     while (curwin->w_cursor.lnum > 1 && *skipwhite(ml_get_curline()) != NUL)
  3628.         --curwin->w_cursor.lnum;
  3629.     }
  3630.     curwin->w_cursor.col = 0;
  3631.  
  3632.     /* Search forward for the identifier, ignore comment lines. */
  3633.     while ((t = searchit(curwin, curbuf, &curwin->w_cursor, FORWARD, pat, 1L, 0,
  3634.                                  RE_LAST)) != FAIL
  3635. #ifdef FEAT_COMMENTS
  3636.         && get_leader_len(ml_get_curline(), NULL, FALSE)
  3637. #endif
  3638.         && old_pos.lnum > curwin->w_cursor.lnum)
  3639.     ++curwin->w_cursor.lnum;
  3640.     if (t == FAIL || old_pos.lnum <= curwin->w_cursor.lnum)
  3641.     {
  3642.     clearopbeep(oap);
  3643.     curwin->w_cursor = old_pos;
  3644.     }
  3645.     else
  3646.     {
  3647.     curwin->w_set_curswant = TRUE;
  3648. #ifdef FEAT_FOLDING
  3649.     if ((fdo_flags & FDO_SEARCH) && KeyTyped && oap->op_type == OP_NOP)
  3650.         foldOpenCursor();
  3651. #endif
  3652.     }
  3653.  
  3654.     vim_free(pat);
  3655.     p_ws = save_p_ws;
  3656.     p_scs = save_p_scs;
  3657. }
  3658.  
  3659. /*
  3660.  * Move 'dist' lines in direction 'dir', counting lines by *screen*
  3661.  * lines rather than lines in the file.
  3662.  * 'dist' must be positive.
  3663.  *
  3664.  * Return OK if able to move cursor, FAIL otherwise.
  3665.  */
  3666.     static int
  3667. nv_screengo(oap, dir, dist)
  3668.     oparg_T    *oap;
  3669.     int        dir;
  3670.     long    dist;
  3671. {
  3672.     int        linelen = linetabsize(ml_get_curline());
  3673.     int        retval = OK;
  3674.     int        atend = FALSE;
  3675.     int        n;
  3676.     int        col_off1;    /* margin offset for first screen line */
  3677.     int        col_off2;    /* margin offset for wrapped screen line */
  3678.     int        width1;        /* text width for first screen line */
  3679.     int        width2;        /* test width for wrapped screen line */
  3680.  
  3681.     oap->motion_type = MCHAR;
  3682.     oap->inclusive = FALSE;
  3683.  
  3684.     col_off1 = curwin_col_off();
  3685.     col_off2 = col_off1 - curwin_col_off2();
  3686.     width1 = W_WIDTH(curwin) - col_off1;
  3687.     width2 = W_WIDTH(curwin) - col_off2;
  3688.  
  3689. #ifdef FEAT_VERTSPLIT
  3690.     if (curwin->w_width != 0)
  3691.     {
  3692. #endif
  3693.       /*
  3694.        * Instead of sticking at the last character of the buffer line we
  3695.        * try to stick in the last column of the screen.
  3696.        */
  3697.       if (curwin->w_curswant == MAXCOL)
  3698.       {
  3699.     atend = TRUE;
  3700.     validate_virtcol();
  3701.     if (width1 <= 0)
  3702.         curwin->w_curswant = 0;
  3703.     else
  3704.     {
  3705.         curwin->w_curswant = width1 - 1;
  3706.         if (curwin->w_virtcol > curwin->w_curswant)
  3707.         curwin->w_curswant += ((curwin->w_virtcol
  3708.                  - curwin->w_curswant - 1) / width2 + 1) * width2;
  3709.     }
  3710.       }
  3711.       else
  3712.       {
  3713.     if (linelen > width1)
  3714.         n = ((linelen - width1 - 1) / width2 + 1) * width2 + width1;
  3715.     else
  3716.         n = width1;
  3717.     if (curwin->w_curswant > (colnr_T)n + 1)
  3718.         curwin->w_curswant -= ((curwin->w_curswant - n) / width2 + 1)
  3719.                                      * width2;
  3720.       }
  3721.  
  3722.       while (dist--)
  3723.       {
  3724.     if (dir == BACKWARD)
  3725.     {
  3726.         if ((long)curwin->w_curswant >= width2)
  3727.         /* move back within line */
  3728.         curwin->w_curswant -= width2;
  3729.         else
  3730.         {
  3731.         /* to previous line */
  3732.         if (curwin->w_cursor.lnum == 1)
  3733.         {
  3734.             retval = FAIL;
  3735.             break;
  3736.         }
  3737.         --curwin->w_cursor.lnum;
  3738. #ifdef FEAT_FOLDING
  3739.         /* Move to the start of a closed fold.  Don't do that when
  3740.          * 'foldopen' contains "all": it will open in a moment. */
  3741.         if (!(fdo_flags & FDO_ALL))
  3742.             (void)hasFolding(curwin->w_cursor.lnum,
  3743.                         &curwin->w_cursor.lnum, NULL);
  3744. #endif
  3745.         linelen = linetabsize(ml_get_curline());
  3746.         if (linelen > width1)
  3747.             curwin->w_curswant += (((linelen - width1 - 1) / width2)
  3748.                                 + 1) * width2;
  3749.         }
  3750.     }
  3751.     else /* dir == FORWARD */
  3752.     {
  3753.         if (linelen > width1)
  3754.         n = ((linelen - width1 - 1) / width2 + 1) * width2 + width1;
  3755.         else
  3756.         n = width1;
  3757.         if (curwin->w_curswant + width2 < (colnr_T)n)
  3758.         /* move forward within line */
  3759.         curwin->w_curswant += width2;
  3760.         else
  3761.         {
  3762.         /* to next line */
  3763. #ifdef FEAT_FOLDING
  3764.         /* Move to the end of a closed fold. */
  3765.         (void)hasFolding(curwin->w_cursor.lnum, NULL,
  3766.                               &curwin->w_cursor.lnum);
  3767. #endif
  3768.         if (curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count)
  3769.         {
  3770.             retval = FAIL;
  3771.             break;
  3772.         }
  3773.         curwin->w_cursor.lnum++;
  3774.         curwin->w_curswant %= width2;
  3775.         }
  3776.     }
  3777.       }
  3778. #ifdef FEAT_VERTSPLIT
  3779.     }
  3780. #endif
  3781.  
  3782.     coladvance(curwin->w_curswant);
  3783.  
  3784. #if defined(FEAT_LINEBREAK) || defined(FEAT_MBYTE)
  3785.     if (curwin->w_cursor.col > 0 && curwin->w_p_wrap)
  3786.     {
  3787.     /*
  3788.      * Check for landing on a character that got split at the end of the
  3789.      * last line.  We want to advance a screenline, not end up in the same
  3790.      * screenline or move two screenlines.
  3791.      */
  3792.     validate_virtcol();
  3793.     if (curwin->w_virtcol > curwin->w_curswant
  3794.         && (curwin->w_curswant < (colnr_T)width1
  3795.             ? (curwin->w_curswant > (colnr_T)width1 / 2)
  3796.             : ((curwin->w_curswant - width1) % width2
  3797.                               > (colnr_T)width2 / 2)))
  3798.         --curwin->w_cursor.col;
  3799.     }
  3800. #endif
  3801.  
  3802.     if (atend)
  3803.     curwin->w_curswant = MAXCOL;        /* stick in the last column */
  3804.  
  3805.     return retval;
  3806. }
  3807.  
  3808. #ifdef FEAT_MOUSE
  3809. /*
  3810.  * Mouse scroll wheel: Default action is to scroll three lines, or one page
  3811.  * when Shift or Ctrl is used.
  3812.  * K_MOUSEUP (cap->arg == TRUE) or K_MOUSEDOWN (cap->arg == FALSE)
  3813.  */
  3814.     static void
  3815. nv_mousescroll(cap)
  3816.     cmdarg_T    *cap;
  3817. {
  3818.     if (mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL))
  3819.     {
  3820.     (void)onepage(cap->arg ? FORWARD : BACKWARD, 1L);
  3821.     }
  3822.     else
  3823.     {
  3824.     cap->count1 = 3;
  3825.     cap->count0 = 3;
  3826.     nv_scroll_line(cap);
  3827.     }
  3828. }
  3829.  
  3830. /*
  3831.  * Mouse clicks and drags.
  3832.  */
  3833.     static void
  3834. nv_mouse(cap)
  3835.     cmdarg_T    *cap;
  3836. {
  3837.     (void)do_mouse(cap->oap, cap->cmdchar, BACKWARD, cap->count1, 0);
  3838. }
  3839. #endif
  3840.  
  3841. /*
  3842.  * Handle CTRL-E and CTRL-Y commands: scroll a line up or down.
  3843.  * cap->arg must be TRUE for CTRL-E.
  3844.  */
  3845.     static void
  3846. nv_scroll_line(cap)
  3847.     cmdarg_T    *cap;
  3848. {
  3849.     if (!checkclearop(cap->oap))
  3850.     scroll_redraw(cap->arg, cap->count1);
  3851. }
  3852.  
  3853. /*
  3854.  * Scroll "count" lines up or down, and redraw.
  3855.  */
  3856.     void
  3857. scroll_redraw(up, count)
  3858.     int        up;
  3859.     long    count;
  3860. {
  3861.     linenr_T    prev_topline = curwin->w_topline;
  3862. #ifdef FEAT_DIFF
  3863.     int        prev_topfill = curwin->w_topfill;
  3864. #endif
  3865.     linenr_T    prev_lnum = curwin->w_cursor.lnum;
  3866.  
  3867.     if (up)
  3868.     scrollup(count, TRUE);
  3869.     else
  3870.     scrolldown(count, TRUE);
  3871.     if (p_so)
  3872.     {
  3873.     /* Adjust the cursor position for 'scrolloff'.  Mark w_topline as
  3874.      * valid, otherwise the screen jumps back at the end of the file. */
  3875.     cursor_correct();
  3876.     check_cursor_moved(curwin);
  3877.     curwin->w_valid |= VALID_TOPLINE;
  3878.  
  3879.     /* If moved back to where we were, at least move the cursor, otherwise
  3880.      * we get stuck at one position.  Don't move the cursor up if the
  3881.      * first line of the buffer is already on the screen */
  3882.     while (curwin->w_topline == prev_topline
  3883. #ifdef FEAT_DIFF
  3884.         && curwin->w_topfill == prev_topfill
  3885. #endif
  3886.         )
  3887.     {
  3888.         if (up)
  3889.         {
  3890.         if (curwin->w_cursor.lnum > prev_lnum
  3891.             || cursor_down(1L, FALSE) == FAIL)
  3892.             break;
  3893.         }
  3894.         else
  3895.         {
  3896.         if (curwin->w_cursor.lnum < prev_lnum
  3897.             || prev_topline == 1L
  3898.             || cursor_up(1L, FALSE) == FAIL)
  3899.             break;
  3900.         }
  3901.         /* Mark w_topline as valid, otherwise the screen jumps back at the
  3902.          * end of the file. */
  3903.         check_cursor_moved(curwin);
  3904.         curwin->w_valid |= VALID_TOPLINE;
  3905.     }
  3906.     }
  3907.     if (curwin->w_cursor.lnum != prev_lnum)
  3908.     coladvance(curwin->w_curswant);
  3909.     redraw_later(VALID);
  3910. }
  3911.  
  3912. /*
  3913.  * Commands that start with "z".
  3914.  */
  3915.     static void
  3916. nv_zet(cap)
  3917.     cmdarg_T  *cap;
  3918. {
  3919.     long    n;
  3920.     colnr_T    col;
  3921.     int        nchar = cap->nchar;
  3922. #ifdef FEAT_FOLDING
  3923.     long    old_fdl = curwin->w_p_fdl;
  3924.     int        old_fen = curwin->w_p_fen;
  3925. #endif
  3926.  
  3927.     if (vim_isdigit(nchar))
  3928.     {
  3929.     if (checkclearop(cap->oap))
  3930.         return;
  3931.     n = nchar - '0';
  3932.     for (;;)
  3933.     {
  3934. #ifdef USE_ON_FLY_SCROLL
  3935.         dont_scroll = TRUE;        /* disallow scrolling here */
  3936. #endif
  3937.         ++no_mapping;
  3938.         ++allow_keys;   /* no mapping for nchar, but allow key codes */
  3939.         nchar = safe_vgetc();
  3940. #ifdef FEAT_LANGMAP
  3941.         LANGMAP_ADJUST(nchar, TRUE);
  3942. #endif
  3943.         --no_mapping;
  3944.         --allow_keys;
  3945. #ifdef FEAT_CMDL_INFO
  3946.         (void)add_to_showcmd(nchar);
  3947. #endif
  3948.         if (nchar == K_DEL || nchar == K_KDEL)
  3949.         n /= 10;
  3950.         else if (vim_isdigit(nchar))
  3951.         n = n * 10 + (nchar - '0');
  3952.         else if (nchar == CR)
  3953.         {
  3954. #ifdef FEAT_GUI
  3955.         need_mouse_correct = TRUE;
  3956. #endif
  3957.         win_setheight((int)n);
  3958.         break;
  3959.         }
  3960.         else if (nchar == 'l'
  3961.             || nchar == 'h'
  3962.             || nchar == K_LEFT
  3963.             || nchar == K_RIGHT)
  3964.         {
  3965.         cap->count1 = n ? n * cap->count1 : cap->count1;
  3966.         goto dozet;
  3967.         }
  3968.         else
  3969.         {
  3970.         clearopbeep(cap->oap);
  3971.         break;
  3972.         }
  3973.     }
  3974.     cap->oap->op_type = OP_NOP;
  3975.     return;
  3976.     }
  3977.  
  3978. dozet:
  3979.     if (
  3980. #ifdef FEAT_FOLDING
  3981.         /* "zf" and "zF" are always an operator, "zd", "zo", "zO", "zc"
  3982.          * and "zC" only in Visual mode. */
  3983.         cap->nchar != 'f' && cap->nchar != 'F'
  3984.         && !(VIsual_active && vim_strchr((char_u *)"dcCoO", cap->nchar))
  3985.         &&
  3986. #endif
  3987.         checkclearop(cap->oap))
  3988.     return;
  3989.  
  3990.     /*
  3991.      * For "z+", "z<CR>", "zt", "z.", "zz", "z^", "z-", "zb":
  3992.      * If line number given, set cursor.
  3993.      */
  3994.     if ((vim_strchr((char_u *)"+\r\nt.z^-b", nchar) != NULL)
  3995.         && cap->count0
  3996.         && cap->count0 != curwin->w_cursor.lnum)
  3997.     {
  3998.     setpcmark();
  3999.     if (cap->count0 > curbuf->b_ml.ml_line_count)
  4000.         curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
  4001.     else
  4002.         curwin->w_cursor.lnum = cap->count0;
  4003.     }
  4004.  
  4005.     switch (nchar)
  4006.     {
  4007.         /* "z+", "z<CR>" and "zt": put cursor at top of screen */
  4008.     case '+':
  4009.         if (cap->count0 == 0)
  4010.         {
  4011.             /* No count given: put cursor at the line below screen */
  4012.             validate_botline();    /* make sure w_botline is valid */
  4013.             if (curwin->w_botline > curbuf->b_ml.ml_line_count)
  4014.             curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
  4015.             else
  4016.             curwin->w_cursor.lnum = curwin->w_botline;
  4017.         }
  4018.         /* FALLTHROUGH */
  4019.     case NL:
  4020.     case CR:
  4021.     case K_KENTER:
  4022.         beginline(BL_WHITE | BL_FIX);
  4023.         /* FALLTHROUGH */
  4024.  
  4025.     case 't':    scroll_cursor_top(0, TRUE);
  4026.         redraw_later(VALID);
  4027.         break;
  4028.  
  4029.         /* "z." and "zz": put cursor in middle of screen */
  4030.     case '.':    beginline(BL_WHITE | BL_FIX);
  4031.         /* FALLTHROUGH */
  4032.  
  4033.     case 'z':    scroll_cursor_halfway(TRUE);
  4034.         redraw_later(VALID);
  4035.         break;
  4036.  
  4037.         /* "z^", "z-" and "zb": put cursor at bottom of screen */
  4038.     case '^':    /* Strange Vi behavior: <count>z^ finds line at top of window
  4039.          * when <count> is at bottom of window, and puts that one at
  4040.          * bottom of window. */
  4041.         if (cap->count0 != 0)
  4042.         {
  4043.             scroll_cursor_bot(0, TRUE);
  4044.             curwin->w_cursor.lnum = curwin->w_topline;
  4045.         }
  4046.         else if (curwin->w_topline == 1)
  4047.             curwin->w_cursor.lnum = 1;
  4048.         else
  4049.             curwin->w_cursor.lnum = curwin->w_topline - 1;
  4050.         /* FALLTHROUGH */
  4051.     case '-':
  4052.         beginline(BL_WHITE | BL_FIX);
  4053.         /* FALLTHROUGH */
  4054.  
  4055.     case 'b':    scroll_cursor_bot(0, TRUE);
  4056.         redraw_later(VALID);
  4057.         break;
  4058.  
  4059.         /* "zH" - scroll screen right half-page */
  4060.     case 'H':
  4061.         cap->count1 *= W_WIDTH(curwin) / 2;
  4062.         /* FALLTHROUGH */
  4063.  
  4064.         /* "zh" - scroll screen to the right */
  4065.     case 'h':
  4066.     case K_LEFT:
  4067.         if (!curwin->w_p_wrap)
  4068.         {
  4069.             if ((colnr_T)cap->count1 > curwin->w_leftcol)
  4070.             curwin->w_leftcol = 0;
  4071.             else
  4072.             curwin->w_leftcol -= (colnr_T)cap->count1;
  4073.             leftcol_changed();
  4074.         }
  4075.         break;
  4076.  
  4077.         /* "zL" - scroll screen left half-page */
  4078.     case 'L':    cap->count1 *= W_WIDTH(curwin) / 2;
  4079.         /* FALLTHROUGH */
  4080.  
  4081.         /* "zl" - scroll screen to the left */
  4082.     case 'l':
  4083.     case K_RIGHT:
  4084.         if (!curwin->w_p_wrap)
  4085.         {
  4086.             /* scroll the window left */
  4087.             curwin->w_leftcol += (colnr_T)cap->count1;
  4088.             leftcol_changed();
  4089.         }
  4090.         break;
  4091.  
  4092.         /* "zs" - scroll screen, cursor at the start */
  4093.     case 's':    if (!curwin->w_p_wrap)
  4094.         {
  4095. #ifdef FEAT_FOLDING
  4096.             if (hasFolding(curwin->w_cursor.lnum, NULL, NULL))
  4097.             col = 0;    /* like the cursor is in col 0 */
  4098.             else
  4099. #endif
  4100.             getvcol(curwin, &curwin->w_cursor, &col, NULL, NULL);
  4101.             if (curwin->w_leftcol != col)
  4102.             {
  4103.             curwin->w_leftcol = col;
  4104.             redraw_later(NOT_VALID);
  4105.             }
  4106.         }
  4107.         break;
  4108.  
  4109.         /* "ze" - scroll screen, cursor at the end */
  4110.     case 'e':    if (!curwin->w_p_wrap)
  4111.         {
  4112. #ifdef FEAT_FOLDING
  4113.             if (hasFolding(curwin->w_cursor.lnum, NULL, NULL))
  4114.             col = 0;    /* like the cursor is in col 0 */
  4115.             else
  4116. #endif
  4117.             getvcol(curwin, &curwin->w_cursor, NULL, NULL, &col);
  4118.             n = W_WIDTH(curwin) - curwin_col_off();
  4119.             if ((long)col < n)
  4120.             col = 0;
  4121.             else
  4122.             col = col - n + 1;
  4123.             if (curwin->w_leftcol != col)
  4124.             {
  4125.             curwin->w_leftcol = col;
  4126.             redraw_later(NOT_VALID);
  4127.             }
  4128.         }
  4129.         break;
  4130.  
  4131. #ifdef FEAT_FOLDING
  4132.         /* "zF": create fold command */
  4133.         /* "zf": create fold operator */
  4134.     case 'F':
  4135.     case 'f':   if (foldManualAllowed(TRUE))
  4136.         {
  4137.             cap->nchar = 'f';
  4138.             nv_operator(cap);
  4139.             curwin->w_p_fen = TRUE;
  4140.  
  4141.             /* "zF" is like "zfzf" */
  4142.             if (nchar == 'F' && cap->oap->op_type == OP_FOLD)
  4143.             {
  4144.             nv_operator(cap);
  4145.             finish_op = TRUE;
  4146.             }
  4147.         }
  4148.         else
  4149.             clearopbeep(cap->oap);
  4150.         break;
  4151.  
  4152.         /* "zd": delete fold at cursor */
  4153.         /* "zD": delete fold at cursor recursively */
  4154.     case 'd':
  4155.     case 'D':    if (foldManualAllowed(FALSE))
  4156.         {
  4157.             if (VIsual_active)
  4158.             nv_operator(cap);
  4159.             else
  4160.             deleteFold(curwin->w_cursor.lnum,
  4161.                   curwin->w_cursor.lnum, nchar == 'D', FALSE);
  4162.         }
  4163.         break;
  4164.  
  4165.         /* "zE": erease all folds */
  4166.     case 'E':    if (foldmethodIsManual(curwin))
  4167.         {
  4168.             clearFolding(curwin);
  4169.             changed_window_setting();
  4170.         }
  4171.         else if (foldmethodIsMarker(curwin))
  4172.             deleteFold((linenr_T)1, curbuf->b_ml.ml_line_count,
  4173.                                  TRUE, FALSE);
  4174.         else
  4175.             EMSG(_("E352: Cannot erase folds with current 'foldmethod'"));
  4176.         break;
  4177.  
  4178.         /* "zn": fold none: reset 'foldenable' */
  4179.     case 'n':    curwin->w_p_fen = FALSE;
  4180.         break;
  4181.  
  4182.         /* "zN": fold Normal: set 'foldenable' */
  4183.     case 'N':    curwin->w_p_fen = TRUE;
  4184.         break;
  4185.  
  4186.         /* "zi": invert folding: toggle 'foldenable' */
  4187.     case 'i':    curwin->w_p_fen = !curwin->w_p_fen;
  4188.         break;
  4189.  
  4190.         /* "za": open closed fold or close open fold at cursor */
  4191.     case 'a':    if (hasFolding(curwin->w_cursor.lnum, NULL, NULL))
  4192.             openFold(curwin->w_cursor.lnum, cap->count1);
  4193.         else
  4194.         {
  4195.             closeFold(curwin->w_cursor.lnum, cap->count1);
  4196.             curwin->w_p_fen = TRUE;
  4197.         }
  4198.         break;
  4199.  
  4200.         /* "zA": open fold at cursor recursively */
  4201.     case 'A':    if (hasFolding(curwin->w_cursor.lnum, NULL, NULL))
  4202.             openFoldRecurse(curwin->w_cursor.lnum);
  4203.         else
  4204.         {
  4205.             closeFoldRecurse(curwin->w_cursor.lnum);
  4206.             curwin->w_p_fen = TRUE;
  4207.         }
  4208.         break;
  4209.  
  4210.         /* "zo": open fold at cursor or Visual area */
  4211.     case 'o':    if (VIsual_active)
  4212.             nv_operator(cap);
  4213.         else
  4214.             openFold(curwin->w_cursor.lnum, cap->count1);
  4215.         break;
  4216.  
  4217.         /* "zO": open fold recursively */
  4218.     case 'O':    if (VIsual_active)
  4219.             nv_operator(cap);
  4220.         else
  4221.             openFoldRecurse(curwin->w_cursor.lnum);
  4222.         break;
  4223.  
  4224.         /* "zc": close fold at cursor or Visual area */
  4225.     case 'c':    if (VIsual_active)
  4226.             nv_operator(cap);
  4227.         else
  4228.             closeFold(curwin->w_cursor.lnum, cap->count1);
  4229.         curwin->w_p_fen = TRUE;
  4230.         break;
  4231.  
  4232.         /* "zC": close fold recursively */
  4233.     case 'C':    if (VIsual_active)
  4234.             nv_operator(cap);
  4235.         else
  4236.             closeFoldRecurse(curwin->w_cursor.lnum);
  4237.         curwin->w_p_fen = TRUE;
  4238.         break;
  4239.  
  4240.         /* "zv": open folds at the cursor */
  4241.     case 'v':    foldOpenCursor();
  4242.         break;
  4243.  
  4244.         /* "zx": re-apply 'foldlevel' and open folds at the cursor */
  4245.     case 'x':    curwin->w_p_fen = TRUE;
  4246.         newFoldLevel();        /* update right now */
  4247.         foldOpenCursor();
  4248.         break;
  4249.  
  4250.         /* "zX": undo manual opens/closes, re-apply 'foldlevel' */
  4251.     case 'X':    curwin->w_p_fen = TRUE;
  4252.         old_fdl = -1;        /* force an update */
  4253.         break;
  4254.  
  4255.         /* "zm": fold more */
  4256.     case 'm':    if (curwin->w_p_fdl > 0)
  4257.             --curwin->w_p_fdl;
  4258.         old_fdl = -1;        /* force an update */
  4259.         curwin->w_p_fen = TRUE;
  4260.         break;
  4261.  
  4262.         /* "zM": close all folds */
  4263.     case 'M':    curwin->w_p_fdl = 0;
  4264.         old_fdl = -1;        /* force an update */
  4265.         curwin->w_p_fen = TRUE;
  4266.         break;
  4267.  
  4268.         /* "zr": reduce folding */
  4269.     case 'r':    ++curwin->w_p_fdl;
  4270.         break;
  4271.  
  4272.         /* "zR": open all folds */
  4273.     case 'R':    curwin->w_p_fdl = getDeepestNesting();
  4274.         old_fdl = -1;        /* force an update */
  4275.         break;
  4276.  
  4277.     case 'j':    /* "zj" move to next fold downwards */
  4278.     case 'k':    /* "zk" move to next fold upwards */
  4279.         if (foldMoveTo(TRUE, nchar == 'j' ? FORWARD : BACKWARD,
  4280.                               cap->count1) == FAIL)
  4281.             clearopbeep(cap->oap);
  4282.         break;
  4283.  
  4284. #endif /* FEAT_FOLDING */
  4285.  
  4286.     default:    clearopbeep(cap->oap);
  4287.     }
  4288.  
  4289. #ifdef FEAT_FOLDING
  4290.     /* Redraw when 'foldenable' or 'foldlevel' changed */
  4291.     if (old_fen != curwin->w_p_fen)
  4292.     changed_window_setting();
  4293.     if (old_fdl != curwin->w_p_fdl)
  4294.     newFoldLevel();
  4295. #endif
  4296. }
  4297.  
  4298. #ifdef FEAT_GUI
  4299. /*
  4300.  * Vertical scrollbar movement.
  4301.  */
  4302.     static void
  4303. nv_ver_scrollbar(cap)
  4304.     cmdarg_T    *cap;
  4305. {
  4306.     if (cap->oap->op_type != OP_NOP)
  4307.     clearopbeep(cap->oap);
  4308.  
  4309.     /* Even if an operator was pending, we still want to scroll */
  4310.     gui_do_scroll();
  4311. }
  4312.  
  4313. /*
  4314.  * Horizontal scrollbar movement.
  4315.  */
  4316.     static void
  4317. nv_hor_scrollbar(cap)
  4318.     cmdarg_T    *cap;
  4319. {
  4320.     if (cap->oap->op_type != OP_NOP)
  4321.     clearopbeep(cap->oap);
  4322.  
  4323.     /* Even if an operator was pending, we still want to scroll */
  4324.     gui_do_horiz_scroll();
  4325. }
  4326. #endif
  4327.  
  4328. /*
  4329.  * "Q" command.
  4330.  */
  4331.     static void
  4332. nv_exmode(cap)
  4333.     cmdarg_T    *cap;
  4334. {
  4335.     /*
  4336.      * Ignore 'Q' in Visual mode, just give a beep.
  4337.      */
  4338. #ifdef FEAT_VISUAL
  4339.     if (VIsual_active)
  4340.     vim_beep();
  4341.     else
  4342. #endif
  4343.     if (!checkclearop(cap->oap))
  4344.     do_exmode(FALSE);
  4345. }
  4346.  
  4347. /*
  4348.  * Handle a ":" command.
  4349.  */
  4350.     static void
  4351. nv_colon(cap)
  4352.     cmdarg_T  *cap;
  4353. {
  4354.     int        old_p_im;
  4355.  
  4356. #ifdef FEAT_VISUAL
  4357.     if (VIsual_active)
  4358.     nv_operator(cap);
  4359.     else
  4360. #endif
  4361.     {
  4362.     if (cap->oap->op_type != OP_NOP)
  4363.     {
  4364.         /* Using ":" as a movement is characterwise exclusive. */
  4365.         cap->oap->motion_type = MCHAR;
  4366.         cap->oap->inclusive = FALSE;
  4367.     }
  4368.     else if (cap->count0)
  4369.     {
  4370.         /* translate "count:" into ":.,.+(count - 1)" */
  4371.         stuffcharReadbuff('.');
  4372.         if (cap->count0 > 1)
  4373.         {
  4374.         stuffReadbuff((char_u *)",.+");
  4375.         stuffnumReadbuff((long)cap->count0 - 1L);
  4376.         }
  4377.     }
  4378.  
  4379.     /* When typing, don't type below an old message */
  4380.     if (KeyTyped)
  4381.         compute_cmdrow();
  4382.  
  4383.     old_p_im = p_im;
  4384.  
  4385.     /* get a command line and execute it */
  4386.     do_cmdline(NULL, getexline, NULL, 0);
  4387.  
  4388.     /* If 'insertmode' changed, enter or exit Insert mode */
  4389.     if (p_im != old_p_im)
  4390.     {
  4391.         if (p_im)
  4392.         restart_edit = 'i';
  4393.         else
  4394.         restart_edit = 0;
  4395.     }
  4396.  
  4397.     /* The start of the operator may have become invalid by the Ex
  4398.      * command. */
  4399.     if (cap->oap->op_type != OP_NOP
  4400.         && (cap->oap->start.lnum > curbuf->b_ml.ml_line_count
  4401.             || cap->oap->start.col >
  4402.                      STRLEN(ml_get(cap->oap->start.lnum))))
  4403.         clearopbeep(cap->oap);
  4404.     }
  4405. }
  4406.  
  4407. /*
  4408.  * Handle CTRL-G command.
  4409.  */
  4410.     static void
  4411. nv_ctrlg(cap)
  4412.     cmdarg_T *cap;
  4413. {
  4414. #ifdef FEAT_VISUAL
  4415.     if (VIsual_active)    /* toggle Selection/Visual mode */
  4416.     {
  4417.     VIsual_select = !VIsual_select;
  4418.     showmode();
  4419.     }
  4420.     else
  4421. #endif
  4422.     if (!checkclearop(cap->oap))
  4423.     /* print full name if count given or :cd used */
  4424.     fileinfo((int)cap->count0, FALSE, TRUE);
  4425. }
  4426.  
  4427. /*
  4428.  * Handle CTRL-H <Backspace> command.
  4429.  */
  4430.     static void
  4431. nv_ctrlh(cap)
  4432.     cmdarg_T *cap;
  4433. {
  4434. #ifdef FEAT_VISUAL
  4435.     if (VIsual_active && VIsual_select)
  4436.     {
  4437.     cap->cmdchar = 'x';    /* BS key behaves like 'x' in Select mode */
  4438.     v_visop(cap);
  4439.     }
  4440.     else
  4441. #endif
  4442.     nv_left(cap);
  4443. }
  4444.  
  4445. /*
  4446.  * CTRL-L: clear screen and redraw.
  4447.  */
  4448.     static void
  4449. nv_clear(cap)
  4450.     cmdarg_T    *cap;
  4451. {
  4452.     if (!checkclearop(cap->oap))
  4453.     {
  4454. #if defined(__BEOS__) && !USE_THREAD_FOR_INPUT_WITH_TIMEOUT
  4455.     /*
  4456.      * Right now, the BeBox doesn't seem to have an easy way to detect
  4457.      * window resizing, so we cheat and make the user detect it
  4458.      * manually with CTRL-L instead
  4459.      */
  4460.     ui_get_shellsize();
  4461. #endif
  4462. #ifdef FEAT_SYN_HL
  4463.     /* Clear all syntax states to force resyncing. */
  4464.     syn_stack_free_all(curbuf);
  4465. #endif
  4466.     redraw_later(CLEAR);
  4467.     }
  4468. }
  4469.  
  4470. /*
  4471.  * CTRL-O: In Select mode: switch to Visual mode for one command.
  4472.  * Otherwise: Go to older pcmark.
  4473.  */
  4474.     static void
  4475. nv_ctrlo(cap)
  4476.     cmdarg_T    *cap;
  4477. {
  4478. #ifdef FEAT_VISUAL
  4479.     if (VIsual_active && VIsual_select)
  4480.     {
  4481.     VIsual_select = FALSE;
  4482.     showmode();
  4483.     restart_VIsual_select = 2;    /* restart Select mode later */
  4484.     }
  4485.     else
  4486. #endif
  4487.     {
  4488.     cap->count1 = -cap->count1;
  4489.     nv_pcmark(cap);
  4490.     }
  4491. }
  4492.  
  4493. /*
  4494.  * CTRL-^ command, short for ":e #"
  4495.  */
  4496.     static void
  4497. nv_hat(cap)
  4498.     cmdarg_T    *cap;
  4499. {
  4500.     if (!checkclearopq(cap->oap))
  4501.     (void)buflist_getfile((int)cap->count0, (linenr_T)0,
  4502.                         GETF_SETMARK|GETF_ALT, FALSE);
  4503. }
  4504.  
  4505. /*
  4506.  * "Z" commands.
  4507.  */
  4508.     static void
  4509. nv_Zet(cap)
  4510.     cmdarg_T *cap;
  4511. {
  4512.     if (!checkclearopq(cap->oap))
  4513.     {
  4514.     switch (cap->nchar)
  4515.     {
  4516.             /* "ZZ": equivalent to ":x". */
  4517.         case 'Z':    do_cmdline_cmd((char_u *)"x");
  4518.             break;
  4519.  
  4520.             /* "ZQ": equivalent to ":q!" (Elvis compatible). */
  4521.         case 'Q':    do_cmdline_cmd((char_u *)"q!");
  4522.             break;
  4523.  
  4524.         default:    clearopbeep(cap->oap);
  4525.     }
  4526.     }
  4527. }
  4528.  
  4529. /*
  4530.  * Handle the commands that use the word under the cursor.
  4531.  * [g] CTRL-]    :ta to current identifier
  4532.  * [g] 'K'    run program for current identifier
  4533.  * [g] '*'    / to current identifier or string
  4534.  * [g] '#'    ? to current identifier or string
  4535.  *  g  ']'    :tselect for current identifier
  4536.  */
  4537.     static void
  4538. nv_ident(cap)
  4539.     cmdarg_T    *cap;
  4540. {
  4541.     char_u    *ptr = NULL;
  4542.     char_u    *buf;
  4543.     char_u    *p;
  4544.     int        n = 0;        /* init for GCC */
  4545.     int        cmdchar;
  4546.     int        g_cmd;        /* "g" command */
  4547.     char_u    *aux_ptr;
  4548.     int        isman;
  4549.     int        isman_s;
  4550.  
  4551.     if (cap->cmdchar == 'g')    /* "g*", "g#", "g]" and "gCTRL-]" */
  4552.     {
  4553.     cmdchar = cap->nchar;
  4554.     g_cmd = TRUE;
  4555.     }
  4556.     else
  4557.     {
  4558.     cmdchar = cap->cmdchar;
  4559.     g_cmd = FALSE;
  4560.     }
  4561.  
  4562.     if (cmdchar == POUND)    /* the pound sign, '#' for English keyboards */
  4563.     cmdchar = '#';
  4564.  
  4565.     /*
  4566.      * The "]", "CTRL-]" and "K" commands accept an argument in Visual mode.
  4567.      */
  4568.     if (cmdchar == ']' || cmdchar == Ctrl_RSB || cmdchar == 'K')
  4569.     {
  4570. #ifdef FEAT_VISUAL
  4571.     if (VIsual_active && get_visual_text(cap, &ptr, &n) == FAIL)
  4572.         return;
  4573. #endif
  4574.     if (checkclearopq(cap->oap))
  4575.         return;
  4576.     }
  4577.  
  4578.     if (ptr == NULL && (n = find_ident_under_cursor(&ptr,
  4579.             (cmdchar == '*' || cmdchar == '#')
  4580.                  ? FIND_IDENT|FIND_STRING : FIND_IDENT)) == 0)
  4581.     {
  4582.     clearop(cap->oap);
  4583.     return;
  4584.     }
  4585.  
  4586.     /* Allocate buffer to put the command in.  Inserting backslashes can
  4587.      * double the length of the word.  p_kp could be added and some numbers. */
  4588.     buf = alloc((unsigned)(n * 2 + 30 + STRLEN(p_kp)));
  4589.     if (buf == NULL)
  4590.     return;
  4591.     buf[0] = NUL;
  4592.  
  4593.     switch (cmdchar)
  4594.     {
  4595.     case '*':
  4596.     case '#':
  4597.         /*
  4598.          * Put cursor at start of word, makes search skip the word
  4599.          * under the cursor.
  4600.          * Call setpcmark() first, so "*``" puts the cursor back where
  4601.          * it was.
  4602.          */
  4603.         setpcmark();
  4604.         curwin->w_cursor.col = (colnr_T) (ptr - ml_get_curline());
  4605.  
  4606.         if (!g_cmd && vim_iswordp(ptr))
  4607.         STRCPY(buf, "\\<");
  4608.         no_smartcase = TRUE;    /* don't use 'smartcase' now */
  4609.         break;
  4610.  
  4611.     case 'K':
  4612.         if (*p_kp == NUL)
  4613.         STRCPY(buf, ":he ");
  4614.         else
  4615.         {
  4616.         /* When a count is given, turn it into a range.  Is this
  4617.          * really what we want? */
  4618.         isman = (STRCMP(p_kp, "man") == 0);
  4619.         isman_s = (STRCMP(p_kp, "man -s") == 0);
  4620.         if (cap->count0 != 0 && !(isman || isman_s))
  4621.             sprintf((char *)buf, ".,.+%ld", cap->count0 - 1);
  4622.  
  4623.         STRCAT(buf, "! ");
  4624.         if (cap->count0 == 0 && isman_s)
  4625.             STRCAT(buf, "man");
  4626.         else
  4627.             STRCAT(buf, p_kp);
  4628.         STRCAT(buf, " ");
  4629.         if (cap->count0 != 0 && (isman || isman_s))
  4630.         {
  4631.             sprintf((char *)buf + STRLEN(buf), "%ld", cap->count0);
  4632.             STRCAT(buf, " ");
  4633.         }
  4634.         }
  4635.         break;
  4636.  
  4637.     case ']':
  4638. #ifdef FEAT_CSCOPE
  4639.         if (p_cst)
  4640.         STRCPY(buf, "cstag ");
  4641.         else
  4642. #endif
  4643.         STRCPY(buf, "ts ");
  4644.         break;
  4645.  
  4646.     default:
  4647.         if (curbuf->b_help)
  4648.         STRCPY(buf, "he ");
  4649.         else if (g_cmd)
  4650.         STRCPY(buf, "tj ");
  4651.         else
  4652.         STRCPY(buf, "ta ");
  4653.     }
  4654.  
  4655.     /*
  4656.      * Now grab the chars in the identifier
  4657.      */
  4658.     if (cmdchar == '*' || cmdchar == '#')
  4659.     aux_ptr = (char_u *)(p_magic ? "/?.*~[^$\\" : "/?^$\\");
  4660.     else if (cmdchar == 'K' && *p_kp != NUL)
  4661.     aux_ptr = escape_chars;
  4662.     else
  4663.     /* Don't escape spaces and Tabs in a tag with a backslash */
  4664.     aux_ptr = (char_u *)"\\|\"";
  4665.     p = buf + STRLEN(buf);
  4666.     while (n-- > 0)
  4667.     {
  4668.     /* put a backslash before \ and some others */
  4669.     if (vim_strchr(aux_ptr, *ptr) != NULL)
  4670.         *p++ = '\\';
  4671. #ifdef FEAT_MBYTE
  4672.     /* When current byte is a part of multibyte character, copy all bytes
  4673.      * of that character. */
  4674.     if (has_mbyte)
  4675.     {
  4676.         int i;
  4677.         int len = (*mb_ptr2len_check)(ptr) - 1;
  4678.  
  4679.         for (i = 0; i < len && n >= 1; ++i, --n)
  4680.         *p++ = *ptr++;
  4681.     }
  4682. #endif
  4683.     *p++ = *ptr++;
  4684.     }
  4685.     *p = NUL;
  4686.  
  4687.     /*
  4688.      * Execute the command.
  4689.      */
  4690.     if (cmdchar == '*' || cmdchar == '#')
  4691.     {
  4692.     if (!g_cmd && (
  4693. #ifdef FEAT_MBYTE
  4694.         has_mbyte ? vim_iswordp(mb_prevptr(ml_get_curline(), ptr)) :
  4695. #endif
  4696.         vim_iswordc(ptr[-1])))
  4697.         STRCAT(buf, "\\>");
  4698. #ifdef FEAT_CMDHIST
  4699.     /* put pattern in search history */
  4700.     add_to_history(HIST_SEARCH, buf, TRUE);
  4701. #endif
  4702.     normal_search(cap, cmdchar == '*' ? '/' : '?', buf, 0);
  4703.     }
  4704.     else
  4705.     do_cmdline_cmd(buf);
  4706.  
  4707.     vim_free(buf);
  4708. }
  4709.  
  4710. #ifdef FEAT_VISUAL
  4711. /*
  4712.  * Get visually selected text, within one line only.
  4713.  * Returns FAIL if more than one line selected.
  4714.  */
  4715.     static int
  4716. get_visual_text(cap, pp, lenp)
  4717.     cmdarg_T    *cap;
  4718.     char_u    **pp;        /* return: start of selected text */
  4719.     int        *lenp;        /* return: length of selected text */
  4720. {
  4721.     if (VIsual_mode != 'V')
  4722.     unadjust_for_sel();
  4723.     if (VIsual.lnum != curwin->w_cursor.lnum)
  4724.     {
  4725.     clearopbeep(cap->oap);
  4726.     return FAIL;
  4727.     }
  4728.     if (VIsual_mode == 'V')
  4729.     {
  4730.     *pp = ml_get_curline();
  4731.     *lenp = (int)STRLEN(*pp);
  4732.     }
  4733.     else if (lt(curwin->w_cursor, VIsual))
  4734.     {
  4735.     *pp = ml_get_pos(&curwin->w_cursor);
  4736.     *lenp = VIsual.col - curwin->w_cursor.col + 1;
  4737.     }
  4738.     else
  4739.     {
  4740.     *pp = ml_get_pos(&VIsual);
  4741.     *lenp = curwin->w_cursor.col - VIsual.col + 1;
  4742.     }
  4743.     reset_VIsual_and_resel();
  4744.     return OK;
  4745. }
  4746. #endif
  4747.  
  4748. /*
  4749.  * CTRL-T: backwards in tag stack
  4750.  */
  4751.     static void
  4752. nv_tagpop(cap)
  4753.     cmdarg_T    *cap;
  4754. {
  4755.     if (!checkclearopq(cap->oap))
  4756.     do_tag((char_u *)"", DT_POP, (int)cap->count1, FALSE, TRUE);
  4757. }
  4758.  
  4759. /*
  4760.  * Handle scrolling command 'H', 'L' and 'M'.
  4761.  */
  4762.     static void
  4763. nv_scroll(cap)
  4764.     cmdarg_T  *cap;
  4765. {
  4766.     int        used = 0;
  4767.     long    n;
  4768. #ifdef FEAT_FOLDING
  4769.     linenr_T    lnum;
  4770. #endif
  4771.     int        half;
  4772.  
  4773.     cap->oap->motion_type = MLINE;
  4774.     setpcmark();
  4775.  
  4776.     if (cap->cmdchar == 'L')
  4777.     {
  4778.     validate_botline();        /* make sure curwin->w_botline is valid */
  4779.     curwin->w_cursor.lnum = curwin->w_botline - 1;
  4780.     if (cap->count1 - 1 >= curwin->w_cursor.lnum)
  4781.         curwin->w_cursor.lnum = 1;
  4782.     else
  4783.         curwin->w_cursor.lnum -= cap->count1 - 1;
  4784.     }
  4785.     else
  4786.     {
  4787.     if (cap->cmdchar == 'M')
  4788.     {
  4789. #ifdef FEAT_DIFF
  4790.         /* Don't count filler lines above the window. */
  4791.         used -= diff_check_fill(curwin, curwin->w_topline)
  4792.                               - curwin->w_topfill;
  4793. #endif
  4794.         validate_botline();        /* make sure w_empty_rows is valid */
  4795.         half = (curwin->w_height - curwin->w_empty_rows + 1) / 2;
  4796.         for (n = 0; curwin->w_topline + n < curbuf->b_ml.ml_line_count; ++n)
  4797.         {
  4798. #ifdef FEAT_DIFF
  4799.         /* Count half he number of filler lines to be "below this
  4800.          * line" and half to be "above the next line". */
  4801.         if (n > 0 && used + diff_check_fill(curwin, curwin->w_topline
  4802.                                  + n) / 2 >= half)
  4803.         {
  4804.             --n;
  4805.             break;
  4806.         }
  4807. #endif
  4808.         used += plines(curwin->w_topline + n);
  4809.         if (used >= half)
  4810.             break;
  4811. #ifdef FEAT_FOLDING
  4812.         if (hasFolding(curwin->w_topline + n, NULL, &lnum))
  4813.             n = lnum - curwin->w_topline;
  4814. #endif
  4815.         }
  4816.         if (n > 0 && used > curwin->w_height)
  4817.         --n;
  4818.     }
  4819.     else
  4820.         n = cap->count1 - 1;
  4821.     curwin->w_cursor.lnum = curwin->w_topline + n;
  4822.     if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
  4823.         curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
  4824.     }
  4825.  
  4826.     cursor_correct();    /* correct for 'so' */
  4827.     beginline(BL_SOL | BL_FIX);
  4828. }
  4829.  
  4830. /*
  4831.  * Cursor right commands.
  4832.  */
  4833.     static void
  4834. nv_right(cap)
  4835.     cmdarg_T    *cap;
  4836. {
  4837.     long    n;
  4838. #ifdef FEAT_VISUAL
  4839.     int        PAST_LINE;
  4840. #else
  4841. # define PAST_LINE 0
  4842. #endif
  4843.  
  4844.     cap->oap->motion_type = MCHAR;
  4845.     cap->oap->inclusive = FALSE;
  4846. #ifdef FEAT_VISUAL
  4847.     PAST_LINE = (VIsual_active && *p_sel != 'o');
  4848.  
  4849. # ifdef FEAT_VIRTUALEDIT
  4850.     /*
  4851.      * In virtual mode, there's no such thing as "PAST_LINE", as lines are
  4852.      * (theoretically) infinitly long.
  4853.      */
  4854.     if (virtual_active())
  4855.     PAST_LINE = 0;
  4856. # endif
  4857. #endif
  4858.  
  4859.     for (n = cap->count1; n > 0; --n)
  4860.     {
  4861.     if ((!PAST_LINE && oneright() == FAIL)
  4862.         || (PAST_LINE && *ml_get_cursor() == NUL))
  4863.     {
  4864.         /*
  4865.          *      <Space> wraps to next line if 'whichwrap' bit 1 set.
  4866.          *          'l' wraps to next line if 'whichwrap' bit 2 set.
  4867.          * CURS_RIGHT wraps to next line if 'whichwrap' bit 3 set
  4868.          */
  4869.         if (       ((cap->cmdchar == ' '
  4870.                 && vim_strchr(p_ww, 's') != NULL)
  4871.             || (cap->cmdchar == 'l'
  4872.                 && vim_strchr(p_ww, 'l') != NULL)
  4873.             || (cap->cmdchar == K_RIGHT
  4874.                 && vim_strchr(p_ww, '>') != NULL))
  4875.             && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count)
  4876.         {
  4877.         /* When deleting we also count the NL as a character.
  4878.          * Set cap->oap->inclusive when last char in the line is
  4879.          * included, move to next line after that */
  4880.         if (       (cap->oap->op_type == OP_DELETE
  4881.                 || cap->oap->op_type == OP_CHANGE)
  4882.             && !cap->oap->inclusive
  4883.             && !lineempty(curwin->w_cursor.lnum))
  4884.             cap->oap->inclusive = TRUE;
  4885.         else
  4886.         {
  4887.             ++curwin->w_cursor.lnum;
  4888.             curwin->w_cursor.col = 0;
  4889. #ifdef FEAT_VIRTUALEDIT
  4890.             curwin->w_cursor.coladd = 0;
  4891. #endif
  4892.             curwin->w_set_curswant = TRUE;
  4893.             cap->oap->inclusive = FALSE;
  4894.         }
  4895.         continue;
  4896.         }
  4897.         if (cap->oap->op_type == OP_NOP)
  4898.         {
  4899.         /* Only beep and flush if not moved at all */
  4900.         if (n == cap->count1)
  4901.             beep_flush();
  4902.         }
  4903.         else
  4904.         {
  4905.         if (!lineempty(curwin->w_cursor.lnum))
  4906.             cap->oap->inclusive = TRUE;
  4907.         }
  4908.         break;
  4909.     }
  4910. #ifdef FEAT_VISUAL
  4911.     else if (PAST_LINE)
  4912.     {
  4913.         curwin->w_set_curswant = TRUE;
  4914. # ifdef FEAT_VIRTUALEDIT
  4915.         if (virtual_active())
  4916.         oneright();
  4917.         else
  4918. # endif
  4919.         {
  4920. # ifdef FEAT_MBYTE
  4921.         if (has_mbyte)
  4922.             curwin->w_cursor.col +=
  4923.                      (*mb_ptr2len_check)(ml_get_cursor());
  4924.         else
  4925. # endif
  4926.             ++curwin->w_cursor.col;
  4927.         }
  4928.     }
  4929. #endif
  4930.     }
  4931. #ifdef FEAT_FOLDING
  4932.     if (n != cap->count1 && (fdo_flags & FDO_HOR) && KeyTyped
  4933.                            && cap->oap->op_type == OP_NOP)
  4934.     foldOpenCursor();
  4935. #endif
  4936. }
  4937.  
  4938. /*
  4939.  * Cursor left commands.
  4940.  *
  4941.  * Returns TRUE when operator end should not be adjusted.
  4942.  */
  4943.     static void
  4944. nv_left(cap)
  4945.     cmdarg_T    *cap;
  4946. {
  4947.     long    n;
  4948.  
  4949.     cap->oap->motion_type = MCHAR;
  4950.     cap->oap->inclusive = FALSE;
  4951.     for (n = cap->count1; n > 0; --n)
  4952.     {
  4953.     if (oneleft() == FAIL)
  4954.     {
  4955.         /* <BS> and <Del> wrap to previous line if 'whichwrap' has 'b'.
  4956.          *         'h' wraps to previous line if 'whichwrap' has 'h'.
  4957.          *       CURS_LEFT wraps to previous line if 'whichwrap' has '<'.
  4958.          */
  4959.         if (       (((cap->cmdchar == K_BS
  4960.                 || cap->cmdchar == Ctrl_H)
  4961.                 && vim_strchr(p_ww, 'b') != NULL)
  4962.             || (cap->cmdchar == 'h'
  4963.                 && vim_strchr(p_ww, 'h') != NULL)
  4964.             || (cap->cmdchar == K_LEFT
  4965.                 && vim_strchr(p_ww, '<') != NULL))
  4966.             && curwin->w_cursor.lnum > 1)
  4967.         {
  4968.         --(curwin->w_cursor.lnum);
  4969.         coladvance((colnr_T)MAXCOL);
  4970.         curwin->w_set_curswant = TRUE;
  4971.  
  4972.         /* When the NL before the first char has to be deleted we
  4973.          * put the cursor on the NUL after the previous line.
  4974.          * This is a very special case, be careful!
  4975.          * don't adjust op_end now, otherwise it won't work */
  4976.         if (       (cap->oap->op_type == OP_DELETE
  4977.                 || cap->oap->op_type == OP_CHANGE)
  4978.             && !lineempty(curwin->w_cursor.lnum))
  4979.         {
  4980.             ++curwin->w_cursor.col;
  4981.             cap->retval |= CA_NO_ADJ_OP_END;
  4982.         }
  4983.         continue;
  4984.         }
  4985.         /* Only beep and flush if not moved at all */
  4986.         else if (cap->oap->op_type == OP_NOP && n == cap->count1)
  4987.         beep_flush();
  4988.         break;
  4989.     }
  4990.     }
  4991. #ifdef FEAT_FOLDING
  4992.     if (n != cap->count1 && (fdo_flags & FDO_HOR) && KeyTyped
  4993.                            && cap->oap->op_type == OP_NOP)
  4994.     foldOpenCursor();
  4995. #endif
  4996. }
  4997.  
  4998. /*
  4999.  * Cursor up commands.
  5000.  * cap->arg is TRUE for "-": Move cursor to first non-blank.
  5001.  */
  5002.     static void
  5003. nv_up(cap)
  5004.     cmdarg_T    *cap;
  5005. {
  5006.     cap->oap->motion_type = MLINE;
  5007.     if (cursor_up(cap->count1, cap->oap->op_type == OP_NOP) == FAIL)
  5008.     clearopbeep(cap->oap);
  5009.     else if (cap->arg)
  5010.     beginline(BL_WHITE | BL_FIX);
  5011. }
  5012.  
  5013. /*
  5014.  * Cursor down commands.
  5015.  * cap->arg is TRUE for CR and "+": Move cursor to first non-blank.
  5016.  */
  5017.     static void
  5018. nv_down(cap)
  5019.     cmdarg_T    *cap;
  5020. {
  5021. #if defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)
  5022.     /* In a quickfix window a <CR> jumps to the error under the cursor. */
  5023.     if (bt_quickfix(curbuf) && cap->cmdchar == '\r')
  5024.     do_cmdline_cmd((char_u *)".cc");
  5025.     else
  5026. #endif
  5027.     {
  5028. #ifdef FEAT_CMDWIN
  5029.     /* In the cmdline window a <CR> executes the command. */
  5030.     if (cmdwin_type != 0 && cap->cmdchar == '\r')
  5031.         cmdwin_result = CR;
  5032.     else
  5033. #endif
  5034.     {
  5035.         cap->oap->motion_type = MLINE;
  5036.         if (cursor_down(cap->count1, cap->oap->op_type == OP_NOP) == FAIL)
  5037.         clearopbeep(cap->oap);
  5038.         else if (cap->arg)
  5039.         beginline(BL_WHITE | BL_FIX);
  5040.     }
  5041.     }
  5042. }
  5043.  
  5044. #ifdef FEAT_SEARCHPATH
  5045. /*
  5046.  * Grab the file name under the cursor and edit it.
  5047.  */
  5048.     static void
  5049. nv_gotofile(cap)
  5050.     cmdarg_T    *cap;
  5051. {
  5052.     char_u    *ptr;
  5053.  
  5054. #ifdef FEAT_CMDWIN
  5055.     if (cmdwin_type != 0)
  5056.     {
  5057.     clearopbeep(cap->oap);
  5058.     return;
  5059.     }
  5060. #endif
  5061.  
  5062. # ifdef FEAT_VISUAL
  5063.     /*
  5064.      * In Visual mode, use the selected text as a file name.
  5065.      * Don't allow selection across multiple lines.
  5066.      */
  5067.     if (VIsual_active)
  5068.     {
  5069.     int    len;
  5070.  
  5071.     if (get_visual_text(cap, &ptr, &len) == FAIL)
  5072.         return;
  5073.     ptr = find_file_name_in_path(ptr, len,
  5074.            FNAME_MESS|FNAME_EXP|FNAME_REL, cap->count1, curbuf->b_ffname);
  5075.     }
  5076.     else
  5077. # endif
  5078.     ptr = file_name_at_cursor(FNAME_MESS|FNAME_HYP|FNAME_EXP|FNAME_REL,
  5079.                                  cap->count1);
  5080.  
  5081.     if (ptr != NULL)
  5082.     {
  5083.     /* do autowrite if necessary */
  5084.     if (curbufIsChanged() && curbuf->b_nwindows <= 1 && !P_HID(curbuf))
  5085.         autowrite(curbuf, FALSE);
  5086.     setpcmark();
  5087.     (void)do_ecmd(0, ptr, NULL, NULL, ECMD_LAST,
  5088.                            P_HID(curbuf) ? ECMD_HIDE : 0);
  5089.     vim_free(ptr);
  5090.     }
  5091.     else
  5092.     clearop(cap->oap);
  5093. }
  5094. #endif
  5095.  
  5096. /*
  5097.  * <End> command: to end of current line or last line.
  5098.  */
  5099.     static void
  5100. nv_end(cap)
  5101.     cmdarg_T    *cap;
  5102. {
  5103.     if (cap->arg)    /* CTRL-END = goto last line */
  5104.     {
  5105.     nv_goto(cap);
  5106.     cap->count1 = 1;        /* to end of current line */
  5107.     }
  5108.     nv_dollar(cap);
  5109. }
  5110.  
  5111. /*
  5112.  * Handle the "$" command.
  5113.  */
  5114.     static void
  5115. nv_dollar(cap)
  5116.     cmdarg_T    *cap;
  5117. {
  5118.     cap->oap->motion_type = MCHAR;
  5119.     cap->oap->inclusive = TRUE;
  5120. #ifdef FEAT_VIRTUALEDIT
  5121.     /* In virtual mode when off the edge of a line and an operator
  5122.      * is pending (whew!) keep the cursor where it is.
  5123.      * Otherwise, send it to the end of the line. */
  5124.     if (!virtual_active() || gchar_cursor() != NUL ||
  5125.         cap->oap->op_type == OP_NOP)
  5126. #endif
  5127.     curwin->w_curswant = MAXCOL;    /* so we stay at the end */
  5128.     if (cursor_down((long)(cap->count1 - 1),
  5129.                      cap->oap->op_type == OP_NOP) == FAIL)
  5130.     clearopbeep(cap->oap);
  5131. #ifdef FEAT_FOLDING
  5132.     else if ((fdo_flags & FDO_HOR) && KeyTyped && cap->oap->op_type == OP_NOP)
  5133.     foldOpenCursor();
  5134. #endif
  5135. }
  5136.  
  5137. /*
  5138.  * Implementation of '?' and '/' commands.
  5139.  * If cap->arg is TRUE don't set PC mark.
  5140.  */
  5141.     static void
  5142. nv_search(cap)
  5143.     cmdarg_T        *cap;
  5144. {
  5145.     oparg_T    *oap = cap->oap;
  5146.  
  5147.     if (cap->cmdchar == '?' && cap->oap->op_type == OP_ROT13)
  5148.     {
  5149.     /* Translate "g??" to "g?g?" */
  5150.     cap->cmdchar = 'g';
  5151.     cap->nchar = '?';
  5152.     nv_operator(cap);
  5153.     return;
  5154.     }
  5155.  
  5156.     cap->searchbuf = getcmdline(cap->cmdchar, cap->count1, 0);
  5157.  
  5158.     if (cap->searchbuf == NULL)
  5159.     {
  5160.     clearop(oap);
  5161.     return;
  5162.     }
  5163.  
  5164.     normal_search(cap, cap->cmdchar, cap->searchbuf,
  5165.                         (cap->arg ? 0 : SEARCH_MARK));
  5166. }
  5167.  
  5168. /*
  5169.  * Handle "N" and "n" commands.
  5170.  * cap->arg is SEARCH_REV for "N", 0 for "n".
  5171.  */
  5172.     static void
  5173. nv_next(cap)
  5174.     cmdarg_T    *cap;
  5175. {
  5176.     normal_search(cap, 0, NULL, SEARCH_MARK | cap->arg);
  5177. }
  5178.  
  5179. /*
  5180.  * Search for "pat" in direction "dir" ('/' or '?', 0 for repeat).
  5181.  * Uses only cap->count1 and cap->oap from "cap".
  5182.  */
  5183.     static void
  5184. normal_search(cap, dir, pat, opt)
  5185.     cmdarg_T    *cap;
  5186.     int        dir;
  5187.     char_u    *pat;
  5188.     int        opt;        /* extra flags for do_search() */
  5189. {
  5190.     int        i;
  5191.  
  5192.     cap->oap->motion_type = MCHAR;
  5193.     cap->oap->inclusive = FALSE;
  5194.     cap->oap->use_reg_one = TRUE;
  5195.     curwin->w_set_curswant = TRUE;
  5196.  
  5197.     i = do_search(cap->oap, dir, pat, cap->count1,
  5198.                  opt | SEARCH_OPT | SEARCH_ECHO | SEARCH_MSG);
  5199.     if (i == 0)
  5200.     clearop(cap->oap);
  5201.     else
  5202.     {
  5203.     if (i == 2)
  5204.         cap->oap->motion_type = MLINE;
  5205. #ifdef FEAT_VIRTUALEDIT
  5206.     curwin->w_cursor.coladd = 0;
  5207. #endif
  5208. #ifdef FEAT_FOLDING
  5209.     if (cap->oap->op_type == OP_NOP && (fdo_flags & FDO_SEARCH) && KeyTyped)
  5210.         foldOpenCursor();
  5211. #endif
  5212.     }
  5213.  
  5214.     /* "/$" will put the cursor after the end of the line, may need to
  5215.      * correct that here */
  5216.     check_cursor();
  5217. }
  5218.  
  5219. /*
  5220.  * Character search commands.
  5221.  * cap->arg is BACKWARD for 'F' and 'T', FORWARD for 'f' and 't', TRUE for
  5222.  * ',' and FALSE for ';'.
  5223.  * cap->nchar is NUL for ',' and ';' (repeat the search)
  5224.  */
  5225.     static void
  5226. nv_csearch(cap)
  5227.     cmdarg_T    *cap;
  5228. {
  5229.     int        t_cmd;
  5230.  
  5231.     if (cap->cmdchar == 't' || cap->cmdchar == 'T')
  5232.     t_cmd = TRUE;
  5233.     else
  5234.     t_cmd = FALSE;
  5235.  
  5236.     cap->oap->motion_type = MCHAR;
  5237.     if (cap->arg == BACKWARD)
  5238.     cap->oap->inclusive = FALSE;
  5239.     else
  5240.     cap->oap->inclusive = TRUE;
  5241.     if (IS_SPECIAL(cap->nchar) || searchc(cap, t_cmd) == FAIL)
  5242.     clearopbeep(cap->oap);
  5243.     else
  5244.     {
  5245.     curwin->w_set_curswant = TRUE;
  5246. #ifdef FEAT_VIRTUALEDIT
  5247.     curwin->w_cursor.coladd = 0;
  5248. #endif
  5249. #ifdef FEAT_VISUAL
  5250.     adjust_for_sel(cap);
  5251. #endif
  5252. #ifdef FEAT_FOLDING
  5253.     if ((fdo_flags & FDO_HOR) && KeyTyped && cap->oap->op_type == OP_NOP)
  5254.         foldOpenCursor();
  5255. #endif
  5256.     }
  5257. }
  5258.  
  5259. /*
  5260.  * "[" and "]" commands.
  5261.  * cap->arg is BACKWARD for "[" and FORWARD for "]".
  5262.  */
  5263.     static void
  5264. nv_brackets(cap)
  5265.     cmdarg_T    *cap;
  5266. {
  5267.     pos_T    new_pos;
  5268.     pos_T    prev_pos;
  5269.     pos_T    *pos = NULL;        /* init for GCC */
  5270.     pos_T    old_pos;        /* cursor position before command */
  5271.     int        flag;
  5272.     long    n;
  5273.     int        findc;
  5274.     int        c;
  5275.  
  5276.     cap->oap->motion_type = MCHAR;
  5277.     cap->oap->inclusive = FALSE;
  5278.     old_pos = curwin->w_cursor;
  5279. #ifdef FEAT_VIRTUALEDIT
  5280.     curwin->w_cursor.coladd = 0;        /* TODO: don't do this for an error. */
  5281. #endif
  5282.  
  5283. #ifdef FEAT_SEARCHPATH
  5284.     /*
  5285.      * "[f" or "]f" : Edit file under the cursor (same as "gf")
  5286.      */
  5287.     if (cap->nchar == 'f')
  5288.     nv_gotofile(cap);
  5289.     else
  5290. #endif
  5291.  
  5292. #ifdef FEAT_FIND_ID
  5293.     /*
  5294.      * Find the occurence(s) of the identifier or define under cursor
  5295.      * in current and included files or jump to the first occurence.
  5296.      *
  5297.      *            search         list        jump
  5298.      *              fwd   bwd    fwd     bwd     fwd    bwd
  5299.      * identifier     "]i"  "[i"   "]I"  "[I"    "]^I"  "[^I"
  5300.      * define          "]d"  "[d"   "]D"  "[D"    "]^D"  "[^D"
  5301.      */
  5302.     if (vim_strchr((char_u *)
  5303. #ifdef EBCDIC
  5304.         "iI\005dD\067",
  5305. #else
  5306.         "iI\011dD\004",
  5307. #endif
  5308.         cap->nchar) != NULL)
  5309.     {
  5310.     char_u    *ptr;
  5311.     int    len;
  5312.  
  5313.     if ((len = find_ident_under_cursor(&ptr, FIND_IDENT)) == 0)
  5314.         clearop(cap->oap);
  5315.     else
  5316.     {
  5317.         find_pattern_in_path(ptr, 0, len, TRUE,
  5318.         cap->count0 == 0 ? !isupper(cap->nchar) : FALSE,
  5319.         ((cap->nchar & 0xf) == ('d' & 0xf)) ?  FIND_DEFINE : FIND_ANY,
  5320.         cap->count1,
  5321.         isupper(cap->nchar) ? ACTION_SHOW_ALL :
  5322.                 islower(cap->nchar) ? ACTION_SHOW : ACTION_GOTO,
  5323.         cap->cmdchar == ']' ? curwin->w_cursor.lnum + 1 : (linenr_T)1,
  5324.         (linenr_T)MAXLNUM);
  5325.         curwin->w_set_curswant = TRUE;
  5326.     }
  5327.     }
  5328.     else
  5329. #endif
  5330.  
  5331.     /*
  5332.      * "[{", "[(", "]}" or "])": go to Nth unclosed '{', '(', '}' or ')'
  5333.      * "[#", "]#": go to start/end of Nth innermost #if..#endif construct.
  5334.      * "[/", "[*", "]/", "]*": go to Nth comment start/end.
  5335.      * "[m" or "]m" search for prev/next start of (Java) method.
  5336.      * "[M" or "]M" search for prev/next end of (Java) method.
  5337.      */
  5338.     if (  (cap->cmdchar == '['
  5339.         && vim_strchr((char_u *)"{(*/#mM", cap->nchar) != NULL)
  5340.         || (cap->cmdchar == ']'
  5341.         && vim_strchr((char_u *)"})*/#mM", cap->nchar) != NULL))
  5342.     {
  5343.     if (cap->nchar == '*')
  5344.         cap->nchar = '/';
  5345.     new_pos.lnum = 0;
  5346.     prev_pos.lnum = 0;
  5347.     if (cap->nchar == 'm' || cap->nchar == 'M')
  5348.     {
  5349.         if (cap->cmdchar == '[')
  5350.         findc = '{';
  5351.         else
  5352.         findc = '}';
  5353.         n = 9999;
  5354.     }
  5355.     else
  5356.     {
  5357.         findc = cap->nchar;
  5358.         n = cap->count1;
  5359.     }
  5360.     for ( ; n > 0; --n)
  5361.     {
  5362.         if ((pos = findmatchlimit(cap->oap, findc,
  5363.         (cap->cmdchar == '[') ? FM_BACKWARD : FM_FORWARD, 0)) == NULL)
  5364.         {
  5365.         if (new_pos.lnum == 0)    /* nothing found */
  5366.         {
  5367.             if (cap->nchar != 'm' && cap->nchar != 'M')
  5368.             clearopbeep(cap->oap);
  5369.         }
  5370.         else
  5371.             pos = &new_pos;    /* use last one found */
  5372.         break;
  5373.         }
  5374.         prev_pos = new_pos;
  5375.         curwin->w_cursor = *pos;
  5376.         new_pos = *pos;
  5377.     }
  5378.     curwin->w_cursor = old_pos;
  5379.  
  5380.     /*
  5381.      * Handle "[m", "]m", "[M" and "[M".  The findmatchlimit() only
  5382.      * brought us to the match for "[m" and "]M" when inside a method.
  5383.      * Try finding the '{' or '}' we want to be at.
  5384.      * Also repeat for the given count.
  5385.      */
  5386.     if (cap->nchar == 'm' || cap->nchar == 'M')
  5387.     {
  5388.         /* norm is TRUE for "]M" and "[m" */
  5389.         int        norm = ((findc == '{') == (cap->nchar == 'm'));
  5390.  
  5391.         n = cap->count1;
  5392.         /* found a match: we were inside a method */
  5393.         if (prev_pos.lnum != 0)
  5394.         {
  5395.         pos = &prev_pos;
  5396.         curwin->w_cursor = prev_pos;
  5397.         if (norm)
  5398.             --n;
  5399.         }
  5400.         else
  5401.         pos = NULL;
  5402.         while (n > 0)
  5403.         {
  5404.         for (;;)
  5405.         {
  5406.             if ((findc == '{' ? dec_cursor() : inc_cursor()) < 0)
  5407.             {
  5408.             /* if not found anything, that's an error */
  5409.             if (pos == NULL)
  5410.                 clearopbeep(cap->oap);
  5411.             n = 0;
  5412.             break;
  5413.             }
  5414.             c = gchar_cursor();
  5415.             if (c == '{' || c == '}')
  5416.             {
  5417.             /* Must have found end/start of class: use it.
  5418.              * Or found the place to be at. */
  5419.             if ((c == findc && norm) || (n == 1 && !norm))
  5420.             {
  5421.                 new_pos = curwin->w_cursor;
  5422.                 pos = &new_pos;
  5423.                 n = 0;
  5424.             }
  5425.             /* if no match found at all, we started outside of the
  5426.              * class and we're inside now.  Just go on. */
  5427.             else if (new_pos.lnum == 0)
  5428.             {
  5429.                 new_pos = curwin->w_cursor;
  5430.                 pos = &new_pos;
  5431.             }
  5432.             /* found start/end of other method: go to match */
  5433.             else if ((pos = findmatchlimit(cap->oap, findc,
  5434.                 (cap->cmdchar == '[') ? FM_BACKWARD : FM_FORWARD,
  5435.                                   0)) == NULL)
  5436.                 n = 0;
  5437.             else
  5438.                 curwin->w_cursor = *pos;
  5439.             break;
  5440.             }
  5441.         }
  5442.         --n;
  5443.         }
  5444.         curwin->w_cursor = old_pos;
  5445.         if (pos == NULL && new_pos.lnum != 0)
  5446.         clearopbeep(cap->oap);
  5447.     }
  5448.     if (pos != NULL)
  5449.     {
  5450.         setpcmark();
  5451.         curwin->w_cursor = *pos;
  5452.         curwin->w_set_curswant = TRUE;
  5453. #ifdef FEAT_FOLDING
  5454.         if ((fdo_flags & FDO_BLOCK) && KeyTyped
  5455.                            && cap->oap->op_type == OP_NOP)
  5456.         foldOpenCursor();
  5457. #endif
  5458.     }
  5459.     }
  5460.  
  5461.     /*
  5462.      * "[[", "[]", "]]" and "][": move to start or end of function
  5463.      */
  5464.     else if (cap->nchar == '[' || cap->nchar == ']')
  5465.     {
  5466.     if (cap->nchar == cap->cmdchar)            /* "]]" or "[[" */
  5467.         flag = '{';
  5468.     else
  5469.         flag = '}';            /* "][" or "[]" */
  5470.  
  5471.     curwin->w_set_curswant = TRUE;
  5472.     /*
  5473.      * Imitate strange Vi behaviour: When using "]]" with an operator
  5474.      * we also stop at '}'.
  5475.      */
  5476.     if (!findpar(cap->oap, cap->arg, cap->count1, flag,
  5477.           (cap->oap->op_type != OP_NOP
  5478.                       && cap->arg == FORWARD && flag == '{')))
  5479.         clearopbeep(cap->oap);
  5480.     else
  5481.     {
  5482.         if (cap->oap->op_type == OP_NOP)
  5483.         beginline(BL_WHITE | BL_FIX);
  5484. #ifdef FEAT_FOLDING
  5485.         if ((fdo_flags & FDO_BLOCK) && KeyTyped && cap->oap->op_type == OP_NOP)
  5486.         foldOpenCursor();
  5487. #endif
  5488.     }
  5489.     }
  5490.  
  5491.     /*
  5492.      * "[p", "[P", "]P" and "]p": put with indent adjustment
  5493.      */
  5494.     else if (cap->nchar == 'p' || cap->nchar == 'P')
  5495.     {
  5496.     if (!checkclearopq(cap->oap))
  5497.     {
  5498.         prep_redo_cmd(cap);
  5499.         do_put(cap->oap->regname,
  5500.           (cap->cmdchar == ']' && cap->nchar == 'p') ? FORWARD : BACKWARD,
  5501.                           cap->count1, PUT_FIXINDENT);
  5502.     }
  5503.     }
  5504.  
  5505.     /*
  5506.      * "['", "[`", "]'" and "]`": jump to next mark
  5507.      */
  5508.     else if (cap->nchar == '\'' || cap->nchar == '`')
  5509.     {
  5510.     pos = &curwin->w_cursor;
  5511.     for (n = cap->count1; n > 0; --n)
  5512.     {
  5513.         prev_pos = *pos;
  5514.         pos = getnextmark(pos, cap->cmdchar == '[' ? BACKWARD : FORWARD,
  5515.                               cap->nchar == '\'');
  5516.         if (pos == NULL)
  5517.         break;
  5518.     }
  5519.     if (pos == NULL)
  5520.         pos = &prev_pos;
  5521.     nv_cursormark(cap, cap->nchar == '\'', pos);
  5522.     }
  5523.  
  5524. #ifdef FEAT_MOUSE
  5525.     /*
  5526.      * [ or ] followed by a middle mouse click: put selected text with
  5527.      * indent adjustment.  Any other button just does as usual.
  5528.      */
  5529.     else if (cap->nchar >= K_LEFTMOUSE && cap->nchar <= K_RIGHTRELEASE)
  5530.     {
  5531.     (void)do_mouse(cap->oap, cap->nchar,
  5532.                (cap->cmdchar == ']') ? FORWARD : BACKWARD,
  5533.                cap->count1, PUT_FIXINDENT);
  5534.     }
  5535. #endif /* FEAT_MOUSE */
  5536.  
  5537. #ifdef FEAT_FOLDING
  5538.     /*
  5539.      * "[z" and "]z": move to start or end of open fold.
  5540.      */
  5541.     else if (cap->nchar == 'z')
  5542.     {
  5543.     if (foldMoveTo(FALSE, cap->cmdchar == ']' ? FORWARD : BACKWARD,
  5544.                              cap->count1) == FAIL)
  5545.         clearopbeep(cap->oap);
  5546.     }
  5547. #endif
  5548.  
  5549. #ifdef FEAT_DIFF
  5550.     /*
  5551.      * "[c" and "]c": move to next or previous diff-change.
  5552.      */
  5553.     else if (cap->nchar == 'c')
  5554.     {
  5555.     if (diff_move_to(cap->cmdchar == ']' ? FORWARD : BACKWARD,
  5556.                              cap->count1) == FAIL)
  5557.         clearopbeep(cap->oap);
  5558.     }
  5559. #endif
  5560.  
  5561.     /* Not a valid cap->nchar. */
  5562.     else
  5563.     clearopbeep(cap->oap);
  5564. }
  5565.  
  5566. /*
  5567.  * Handle Normal mode "%" command.
  5568.  */
  5569.     static void
  5570. nv_percent(cap)
  5571.     cmdarg_T    *cap;
  5572. {
  5573.     pos_T    *pos;
  5574. #ifdef FEAT_FOLDING
  5575.     linenr_T    lnum = curwin->w_cursor.lnum;
  5576. #endif
  5577.  
  5578.     cap->oap->inclusive = TRUE;
  5579.     if (cap->count0)        /* {cnt}% : goto {cnt} percentage in file */
  5580.     {
  5581.     if (cap->count0 > 100)
  5582.         clearopbeep(cap->oap);
  5583.     else
  5584.     {
  5585.         cap->oap->motion_type = MLINE;
  5586.         setpcmark();
  5587.                 /* round up, so CTRL-G will give same value */
  5588.         curwin->w_cursor.lnum = (curbuf->b_ml.ml_line_count *
  5589.                             cap->count0 + 99L) / 100L;
  5590.         beginline(BL_SOL | BL_FIX);
  5591.     }
  5592.     }
  5593.     else            /* "%" : go to matching paren */
  5594.     {
  5595.     cap->oap->motion_type = MCHAR;
  5596.     cap->oap->use_reg_one = TRUE;
  5597.     if ((pos = findmatch(cap->oap, NUL)) == NULL)
  5598.         clearopbeep(cap->oap);
  5599.     else
  5600.     {
  5601.         setpcmark();
  5602.         curwin->w_cursor = *pos;
  5603.         curwin->w_set_curswant = TRUE;
  5604. #ifdef FEAT_VIRTUALEDIT
  5605.         curwin->w_cursor.coladd = 0;
  5606. #endif
  5607. #ifdef FEAT_VISUAL
  5608.         adjust_for_sel(cap);
  5609. #endif
  5610.     }
  5611.     }
  5612. #ifdef FEAT_FOLDING
  5613.     if (cap->oap->op_type == OP_NOP
  5614.         && lnum != curwin->w_cursor.lnum
  5615.         && (fdo_flags & FDO_PERCENT)
  5616.         && KeyTyped)
  5617.     foldOpenCursor();
  5618. #endif
  5619. }
  5620.  
  5621. /*
  5622.  * Handle "(" and ")" commands.
  5623.  * cap->arg is BACKWARD for "(" and FORWARD for ")".
  5624.  */
  5625.     static void
  5626. nv_brace(cap)
  5627.     cmdarg_T    *cap;
  5628. {
  5629.     cap->oap->motion_type = MCHAR;
  5630.     cap->oap->use_reg_one = TRUE;
  5631.     if (cap->cmdchar == ')')
  5632.     cap->oap->inclusive = FALSE;
  5633.     else
  5634.     cap->oap->inclusive = TRUE;
  5635.     curwin->w_set_curswant = TRUE;
  5636.  
  5637.     if (findsent(cap->arg, cap->count1) == FAIL)
  5638.     clearopbeep(cap->oap);
  5639.     else
  5640.     {
  5641. #ifdef FEAT_VIRTUALEDIT
  5642.     curwin->w_cursor.coladd = 0;
  5643. #endif
  5644. #ifdef FEAT_FOLDING
  5645.     if ((fdo_flags & FDO_BLOCK) && KeyTyped && cap->oap->op_type == OP_NOP)
  5646.         foldOpenCursor();
  5647. #endif
  5648.     }
  5649. }
  5650.  
  5651. /*
  5652.  * "m" command: Mark a position.
  5653.  */
  5654.     static void
  5655. nv_mark(cap)
  5656.     cmdarg_T    *cap;
  5657. {
  5658.     if (!checkclearop(cap->oap))
  5659.     {
  5660.     if (setmark(cap->nchar) == FAIL)
  5661.         clearopbeep(cap->oap);
  5662.     }
  5663. }
  5664.  
  5665. /*
  5666.  * "{" and "}" commands.
  5667.  * cmd->arg is BACKWARD for "{" and FORWARD for "}".
  5668.  */
  5669.     static void
  5670. nv_findpar(cap)
  5671.     cmdarg_T    *cap;
  5672. {
  5673.     cap->oap->motion_type = MCHAR;
  5674.     cap->oap->inclusive = FALSE;
  5675.     cap->oap->use_reg_one = TRUE;
  5676.     curwin->w_set_curswant = TRUE;
  5677.     if (!findpar(cap->oap, cap->arg, cap->count1, NUL, FALSE))
  5678.     clearopbeep(cap->oap);
  5679.     else
  5680.     {
  5681. #ifdef FEAT_VIRTUALEDIT
  5682.     curwin->w_cursor.coladd = 0;
  5683. #endif
  5684. #ifdef FEAT_FOLDING
  5685.     if ((fdo_flags & FDO_BLOCK) && KeyTyped && cap->oap->op_type == OP_NOP)
  5686.         foldOpenCursor();
  5687. #endif
  5688.     }
  5689. }
  5690.  
  5691. /*
  5692.  * "u" command: Undo or make lower case.
  5693.  */
  5694.     static void
  5695. nv_undo(cap)
  5696.     cmdarg_T    *cap;
  5697. {
  5698.     if (cap->oap->op_type == OP_LOWER
  5699. #ifdef FEAT_VISUAL
  5700.         || VIsual_active
  5701. #endif
  5702.         )
  5703.     {
  5704.     /* translate "<Visual>u" to "<Visual>gu" and "guu" to "gugu" */
  5705.     cap->cmdchar = 'g';
  5706.     cap->nchar = 'u';
  5707.     nv_operator(cap);
  5708.     }
  5709.     else
  5710.     nv_kundo(cap);
  5711. }
  5712.  
  5713. /*
  5714.  * <Undo> command.
  5715.  */
  5716.     static void
  5717. nv_kundo(cap)
  5718.     cmdarg_T    *cap;
  5719. {
  5720.     if (!checkclearopq(cap->oap))
  5721.     {
  5722.     u_undo((int)cap->count1);
  5723.     curwin->w_set_curswant = TRUE;
  5724.     }
  5725. }
  5726.  
  5727. /*
  5728.  * Handle the "r" command.
  5729.  */
  5730.     static void
  5731. nv_replace(cap)
  5732.     cmdarg_T    *cap;
  5733. {
  5734.     char_u    *ptr;
  5735.     int        had_ctrl_v;
  5736.     long    n;
  5737.  
  5738.     if (checkclearop(cap->oap))
  5739.     return;
  5740.  
  5741.     /* get another character */
  5742.     if (cap->nchar == Ctrl_V)
  5743.     {
  5744.     had_ctrl_v = Ctrl_V;
  5745.     cap->nchar = get_literal();
  5746.     /* Don't redo a multibyte character with CTRL-V. */
  5747.     if (cap->nchar > DEL)
  5748.         had_ctrl_v = NUL;
  5749.     }
  5750.     else
  5751.     had_ctrl_v = NUL;
  5752.  
  5753. #ifdef FEAT_VISUAL
  5754.     /* Visual mode "r" */
  5755.     if (VIsual_active)
  5756.     {
  5757.     nv_operator(cap);
  5758.     return;
  5759.     }
  5760. #endif
  5761.  
  5762. #ifdef FEAT_VIRTUALEDIT
  5763.     /* Break tabs, etc. */
  5764.     if (virtual_active())
  5765.     {
  5766.     u_save_cursor();
  5767.     if (gchar_cursor() == NUL)
  5768.     {
  5769.         /* Add extra space and put the cursor on the first one. */
  5770.         coladvance_force((colnr_T)(getviscol() + cap->count1));
  5771.         curwin->w_cursor.col -= cap->count1;
  5772.     }
  5773.     else if (gchar_cursor() == TAB)
  5774.         coladvance_force(getviscol());
  5775.     }
  5776. #endif
  5777.  
  5778.     /*
  5779.      * Check for a special key or not enough characters to replace.
  5780.      */
  5781.     ptr = ml_get_cursor();
  5782.     if (IS_SPECIAL(cap->nchar) || STRLEN(ptr) < (unsigned)cap->count1
  5783. #ifdef FEAT_MBYTE
  5784.         || (has_mbyte && mb_charlen(ptr) < cap->count1)
  5785. #endif
  5786.         )
  5787.     {
  5788.     clearopbeep(cap->oap);
  5789.     return;
  5790.     }
  5791.  
  5792.     /*
  5793.      * Replacing with a TAB is done by edit(), because it is complicated when
  5794.      * 'expandtab', 'smarttab' or 'softtabstop' is set.
  5795.      * Other characters are done below to avoid problems with things like
  5796.      * CTRL-V 048 (for edit() this would be R CTRL-V 0 ESC).
  5797.      */
  5798.     if (cap->nchar == '\t' && (curbuf->b_p_et || p_sta))
  5799.     {
  5800.     stuffnumReadbuff(cap->count1);
  5801.     stuffcharReadbuff('R');
  5802.     stuffcharReadbuff('\t');
  5803.     stuffcharReadbuff(ESC);
  5804.     return;
  5805.     }
  5806.  
  5807.     /* save line for undo */
  5808.     if (u_save_cursor() == FAIL)
  5809.     return;
  5810.  
  5811.     if (had_ctrl_v != Ctrl_V && (cap->nchar == '\r' || cap->nchar == '\n'))
  5812.     {
  5813.     /*
  5814.      * Replace character(s) by a single newline.
  5815.      * Strange vi behaviour: Only one newline is inserted.
  5816.      * Delete the characters here.
  5817.      * Insert the newline with an insert command, takes care of
  5818.      * autoindent.    The insert command depends on being on the last
  5819.      * character of a line or not.
  5820.      */
  5821. #ifdef FEAT_MBYTE
  5822.     (void)del_chars(cap->count1, FALSE);    /* delete the characters */
  5823. #else
  5824.     (void)del_bytes(cap->count1, FALSE);    /* delete the characters */
  5825. #endif
  5826.     stuffcharReadbuff('\r');
  5827.     stuffcharReadbuff(ESC);
  5828.     /*
  5829.      * Give 'r' to edit(), to get the redo command right.
  5830.      */
  5831.     if (edit('r', FALSE, cap->count1))
  5832.         cap->retval |= CA_COMMAND_BUSY;
  5833.     }
  5834.     else
  5835.     {
  5836.     prep_redo(cap->oap->regname, cap->count1,
  5837.                        NUL, 'r', NUL, had_ctrl_v, cap->nchar);
  5838.  
  5839.     curbuf->b_op_start = curwin->w_cursor;
  5840. #ifdef FEAT_MBYTE
  5841.     if (has_mbyte)
  5842.     {
  5843.         int        old_State = State;
  5844.  
  5845.         /* This is slow, but it handles replacing a single-byte with a
  5846.          * multi-byte and the other way around.  Also handles adding
  5847.          * composing characters for utf-8. */
  5848.         for (n = cap->count1; n > 0; --n)
  5849.         {
  5850.         State = REPLACE;
  5851.         ins_char(cap->nchar);
  5852.         State = old_State;
  5853.         if (cap->ncharC1 != 0)
  5854.             ins_char(cap->ncharC1);
  5855.         if (cap->ncharC2 != 0)
  5856.             ins_char(cap->ncharC2);
  5857.         }
  5858.     }
  5859.     else
  5860. #endif
  5861.     {
  5862.         /*
  5863.          * Replace the characters within one line.
  5864.          */
  5865.         for (n = cap->count1; n > 0; --n)
  5866.         {
  5867.         /*
  5868.          * Get ptr again, because u_save and/or showmatch() will have
  5869.          * released the line.  At the same time we let know that the
  5870.          * line will be changed.
  5871.          */
  5872.         ptr = ml_get_buf(curbuf, curwin->w_cursor.lnum, TRUE);
  5873.         ptr[curwin->w_cursor.col] = cap->nchar;
  5874.         if (       p_sm
  5875.             && msg_silent == 0
  5876.             && (cap->nchar == ')'
  5877.                 || cap->nchar == '}'
  5878.                 || cap->nchar == ']'))
  5879.             showmatch();
  5880.         ++curwin->w_cursor.col;
  5881.         }
  5882.  
  5883.         /* mark the buffer as changed and prepare for displaying */
  5884.         changed_bytes(curwin->w_cursor.lnum,
  5885.                    (colnr_T)(curwin->w_cursor.col - cap->count1));
  5886.     }
  5887.     --curwin->w_cursor.col;        /* cursor on the last replaced char */
  5888. #ifdef FEAT_MBYTE
  5889.     /* if the character on the left of the current cursor is a multi-byte
  5890.      * character, move two characters left */
  5891.     if (has_mbyte)
  5892.         mb_adjust_cursor();
  5893. #endif
  5894.     curbuf->b_op_end = curwin->w_cursor;
  5895.     curwin->w_set_curswant = TRUE;
  5896.     set_last_insert(cap->nchar);
  5897.     }
  5898. }
  5899.  
  5900. #ifdef FEAT_VISUAL
  5901. /*
  5902.  * 'o': Exchange start and end of Visual area.
  5903.  * 'O': same, but in block mode exchange left and right corners.
  5904.  */
  5905.     static void
  5906. v_swap_corners(cmdchar)
  5907.     int        cmdchar;
  5908. {
  5909.     pos_T    old_cursor;
  5910.     colnr_T    left, right;
  5911.  
  5912.     if (cmdchar == 'O' && VIsual_mode == Ctrl_V)
  5913.     {
  5914.     old_cursor = curwin->w_cursor;
  5915.     getvcols(curwin, &old_cursor, &VIsual, &left, &right);
  5916.     curwin->w_cursor.lnum = VIsual.lnum;
  5917.     coladvance(left);
  5918.     VIsual = curwin->w_cursor;
  5919.  
  5920.     curwin->w_cursor.lnum = old_cursor.lnum;
  5921.     curwin->w_curswant = right;
  5922.     /* 'selection "exclusive" and cursor at right-bottom corner: move it
  5923.      * right one column */
  5924.     if (old_cursor.lnum >= VIsual.lnum && *p_sel == 'e')
  5925.         ++curwin->w_curswant;
  5926.     coladvance(curwin->w_curswant);
  5927.     if (curwin->w_cursor.col == old_cursor.col
  5928. #ifdef FEAT_VIRTUALEDIT
  5929.         && (!virtual_active()
  5930.             || curwin->w_cursor.coladd == old_cursor.coladd)
  5931. #endif
  5932.         )
  5933.     {
  5934.         curwin->w_cursor.lnum = VIsual.lnum;
  5935.         if (old_cursor.lnum <= VIsual.lnum && *p_sel == 'e')
  5936.         ++right;
  5937.         coladvance(right);
  5938.         VIsual = curwin->w_cursor;
  5939.  
  5940.         curwin->w_cursor.lnum = old_cursor.lnum;
  5941.         coladvance(left);
  5942.         curwin->w_curswant = left;
  5943.     }
  5944.     }
  5945.     else
  5946.     {
  5947.     old_cursor = curwin->w_cursor;
  5948.     curwin->w_cursor = VIsual;
  5949.     VIsual = old_cursor;
  5950.     curwin->w_set_curswant = TRUE;
  5951.     }
  5952. }
  5953. #endif /* FEAT_VISUAL */
  5954.  
  5955. /*
  5956.  * "R" (cap->arg is FALSE) and "gR" (cap->arg is TRUE).
  5957.  */
  5958.     static void
  5959. nv_Replace(cap)
  5960.     cmdarg_T        *cap;
  5961. {
  5962. #ifdef FEAT_VISUAL
  5963.     if (VIsual_active)        /* "R" is replace lines */
  5964.     {
  5965.     cap->cmdchar = 'c';
  5966.     cap->nchar = NUL;
  5967.     VIsual_mode = 'V';
  5968.     nv_operator(cap);
  5969.     }
  5970.     else
  5971. #endif
  5972.     if (!checkclearopq(cap->oap))
  5973.     {
  5974.     if (!curbuf->b_p_ma)
  5975.         EMSG(_(e_modifiable));
  5976.     else
  5977.     {
  5978. #ifdef FEAT_VIRTUALEDIT
  5979.         if (virtual_active())
  5980.         coladvance(getviscol());
  5981. #endif
  5982.         /* This is a new edit command, not a restart.  We don't edit
  5983.          * recursively. */
  5984.         restart_edit = 0;
  5985.         if (edit(cap->arg ? 'V' : 'R', FALSE, cap->count1))
  5986.         cap->retval |= CA_COMMAND_BUSY;
  5987.     }
  5988.     }
  5989. }
  5990.  
  5991. #ifdef FEAT_VREPLACE
  5992. /*
  5993.  * "gr".
  5994.  */
  5995.     static void
  5996. nv_vreplace(cap)
  5997.     cmdarg_T    *cap;
  5998. {
  5999.     int        restart_edit_save;
  6000.  
  6001. # ifdef FEAT_VISUAL
  6002.     if (VIsual_active)
  6003.     {
  6004.     cap->cmdchar = 'r';
  6005.     cap->nchar = cap->extra_char;
  6006.     nv_replace(cap);    /* Do same as "r" in Visual mode for now */
  6007.     }
  6008.     else
  6009. # endif
  6010.     if (!checkclearopq(cap->oap))
  6011.     {
  6012.     if (!curbuf->b_p_ma)
  6013.         EMSG(_(e_modifiable));
  6014.     else
  6015.     {
  6016.         if (cap->extra_char == Ctrl_V)    /* get another character */
  6017.         cap->extra_char = get_literal();
  6018.         stuffcharReadbuff(cap->extra_char);
  6019.         stuffcharReadbuff(ESC);
  6020. # ifdef FEAT_VIRTUALEDIT
  6021.         if (virtual_active())
  6022.         coladvance(getviscol());
  6023. # endif
  6024.         /* This is a new edit command, not a restart.  Do allow using
  6025.          * CTRL-O rx from Insert mode. */
  6026.         restart_edit_save = restart_edit;
  6027.         restart_edit = 0;
  6028.         if (edit('v', FALSE, cap->count1))
  6029.         cap->retval |= CA_COMMAND_BUSY;
  6030.         if (restart_edit == 0)
  6031.         restart_edit = restart_edit_save;
  6032.     }
  6033.     }
  6034. }
  6035. #endif
  6036.  
  6037. /*
  6038.  * Swap case for "~" command, when it does not work like an operator.
  6039.  */
  6040.     static void
  6041. n_swapchar(cap)
  6042.     cmdarg_T    *cap;
  6043. {
  6044.     long    n;
  6045.     pos_T    startpos;
  6046.     int        did_change = 0;
  6047.  
  6048.     if (checkclearopq(cap->oap))
  6049.     return;
  6050.  
  6051.     if (lineempty(curwin->w_cursor.lnum) && vim_strchr(p_ww, '~') == NULL)
  6052.     {
  6053.     clearopbeep(cap->oap);
  6054.     return;
  6055.     }
  6056.  
  6057.     prep_redo_cmd(cap);
  6058.  
  6059.     if (u_save_cursor() == FAIL)
  6060.     return;
  6061.  
  6062.     startpos = curwin->w_cursor;
  6063.     for (n = cap->count1; n > 0; --n)
  6064.     {
  6065.     did_change |= swapchar(cap->oap->op_type, &curwin->w_cursor);
  6066.     inc_cursor();
  6067.     if (gchar_cursor() == NUL)
  6068.     {
  6069.         if (vim_strchr(p_ww, '~') != NULL
  6070.             && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count)
  6071.         {
  6072.         ++curwin->w_cursor.lnum;
  6073.         curwin->w_cursor.col = 0;
  6074.         if (n > 1)
  6075.         {
  6076.             if (u_savesub(curwin->w_cursor.lnum) == FAIL)
  6077.             break;
  6078.             u_clearline();
  6079.         }
  6080.         }
  6081.         else
  6082.         break;
  6083.     }
  6084.     }
  6085.  
  6086.     check_cursor();
  6087.     curwin->w_set_curswant = TRUE;
  6088.     if (did_change)
  6089.     {
  6090.     changed_lines(startpos.lnum, startpos.col, curwin->w_cursor.lnum + 1,
  6091.                                       0L);
  6092.     curbuf->b_op_start = startpos;
  6093.     curbuf->b_op_end = curwin->w_cursor;
  6094.     if (curbuf->b_op_end.col > 0)
  6095.         --curbuf->b_op_end.col;
  6096.     }
  6097. }
  6098.  
  6099. /*
  6100.  * Move cursor to mark.
  6101.  */
  6102.     static void
  6103. nv_cursormark(cap, flag, pos)
  6104.     cmdarg_T    *cap;
  6105.     int        flag;
  6106.     pos_T    *pos;
  6107. {
  6108.     if (check_mark(pos) == FAIL)
  6109.     clearop(cap->oap);
  6110.     else
  6111.     {
  6112.     if (cap->cmdchar == '\''
  6113.         || cap->cmdchar == '`'
  6114.         || cap->cmdchar == '['
  6115.         || cap->cmdchar == ']')
  6116.         setpcmark();
  6117.     curwin->w_cursor = *pos;
  6118.     if (flag)
  6119.         beginline(BL_WHITE | BL_FIX);
  6120.     else
  6121.         check_cursor();
  6122.     }
  6123.     cap->oap->motion_type = flag ? MLINE : MCHAR;
  6124.     if (cap->cmdchar == '`')
  6125.     cap->oap->use_reg_one = TRUE;
  6126.     cap->oap->inclusive = FALSE;        /* ignored if not MCHAR */
  6127.     curwin->w_set_curswant = TRUE;
  6128. }
  6129.  
  6130. #ifdef FEAT_VISUAL
  6131. /*
  6132.  * Handle commands that are operators in Visual mode.
  6133.  */
  6134.     static void
  6135. v_visop(cap)
  6136.     cmdarg_T    *cap;
  6137. {
  6138.     static char_u trans[] = "YyDdCcxdXdAAIIrr";
  6139.  
  6140.     /* Uppercase means linewise, except in block mode, then "D" deletes till
  6141.      * the end of the line, and "C" replaces til EOL */
  6142.     if (isupper(cap->cmdchar))
  6143.     {
  6144.     if (VIsual_mode != Ctrl_V)
  6145.         VIsual_mode = 'V';
  6146.     else if (cap->cmdchar == 'C' || cap->cmdchar == 'D')
  6147.         curwin->w_curswant = MAXCOL;
  6148.     }
  6149.     cap->cmdchar = *(vim_strchr(trans, cap->cmdchar) + 1);
  6150.     nv_operator(cap);
  6151. }
  6152. #endif
  6153.  
  6154. /*
  6155.  * "s" and "S" commands.
  6156.  */
  6157.     static void
  6158. nv_subst(cap)
  6159.     cmdarg_T    *cap;
  6160. {
  6161. #ifdef FEAT_VISUAL
  6162.     if (VIsual_active)    /* "vs" and "vS" are the same as "vc" */
  6163.     {
  6164.     if (cap->cmdchar == 'S')
  6165.         VIsual_mode = 'V';
  6166.     cap->cmdchar = 'c';
  6167.     nv_operator(cap);
  6168.     }
  6169.     else
  6170. #endif
  6171.     nv_optrans(cap);
  6172. }
  6173.  
  6174. /*
  6175.  * Abbreviated commands.
  6176.  */
  6177.     static void
  6178. nv_abbrev(cap)
  6179.     cmdarg_T    *cap;
  6180. {
  6181.     if (cap->cmdchar == K_DEL || cap->cmdchar == K_KDEL)
  6182.     cap->cmdchar = 'x';        /* DEL key behaves like 'x' */
  6183.  
  6184. #ifdef FEAT_VISUAL
  6185.     /* in Visual mode these commands are operators */
  6186.     if (VIsual_active)
  6187.     v_visop(cap);
  6188.     else
  6189. #endif
  6190.     nv_optrans(cap);
  6191. }
  6192.  
  6193. /*
  6194.  * Translate a command into another command.
  6195.  */
  6196.     static void
  6197. nv_optrans(cap)
  6198.     cmdarg_T    *cap;
  6199. {
  6200.     static char_u *(ar[8]) = {(char_u *)"dl", (char_u *)"dh",
  6201.                   (char_u *)"d$", (char_u *)"c$",
  6202.                   (char_u *)"cl", (char_u *)"cc",
  6203.                   (char_u *)"yy", (char_u *)":s\r"};
  6204.     static char_u *str = (char_u *)"xXDCsSY&";
  6205.  
  6206.     if (!checkclearopq(cap->oap))
  6207.     {
  6208.     if (cap->count0)
  6209.         stuffnumReadbuff(cap->count0);
  6210.     stuffReadbuff(ar[(int)(vim_strchr(str, cap->cmdchar) - str)]);
  6211.     }
  6212.     cap->opcount = 0;
  6213. }
  6214.  
  6215. /*
  6216.  * "'" and "`" commands.  Also for "g'" and "g`".
  6217.  * cap->arg is TRUE for "'" and "g'".
  6218.  */
  6219.     static void
  6220. nv_gomark(cap)
  6221.     cmdarg_T    *cap;
  6222. {
  6223.     pos_T    *pos;
  6224.     int        c;
  6225. #ifdef FEAT_FOLDING
  6226.     linenr_T    lnum = curwin->w_cursor.lnum;
  6227.     int        old_KeyTyped = KeyTyped;    /* getting file may reset it */
  6228. #endif
  6229.  
  6230.     if (cap->cmdchar == 'g')
  6231.     c = cap->extra_char;
  6232.     else
  6233.     c = cap->nchar;
  6234.     pos = getmark(c, (cap->oap->op_type == OP_NOP));
  6235.     if (pos == (pos_T *)-1)        /* jumped to other file */
  6236.     {
  6237.     if (cap->arg)
  6238.     {
  6239.         check_cursor_lnum();
  6240.         beginline(BL_WHITE | BL_FIX);
  6241.     }
  6242.     else
  6243.         check_cursor();
  6244.     }
  6245.     else
  6246.     nv_cursormark(cap, cap->arg, pos);
  6247.  
  6248. #ifdef FEAT_VIRTUALEDIT
  6249.     /* May need to clear the coladd that a mark includes. */
  6250.     if (!virtual_active())
  6251.     curwin->w_cursor.coladd = 0;
  6252. #endif
  6253. #ifdef FEAT_FOLDING
  6254.     if (cap->oap->op_type == OP_NOP
  6255.         && (pos == (pos_T *)-1 || lnum != curwin->w_cursor.lnum)
  6256.         && (fdo_flags & FDO_MARK)
  6257.         && old_KeyTyped)
  6258.     foldOpenCursor();
  6259. #endif
  6260. }
  6261.  
  6262. /*
  6263.  * Handle CTRL-O and CTRL-I commands.
  6264.  */
  6265.     static void
  6266. nv_pcmark(cap)
  6267.     cmdarg_T    *cap;
  6268. {
  6269. #ifdef FEAT_JUMPLIST
  6270.     pos_T    *pos;
  6271. # ifdef FEAT_FOLDING
  6272.     linenr_T    lnum = curwin->w_cursor.lnum;
  6273.     int        old_KeyTyped = KeyTyped;    /* getting file may reset it */
  6274. # endif
  6275.  
  6276.     if (!checkclearopq(cap->oap))
  6277.     {
  6278.     pos = movemark((int)cap->count1);
  6279.     if (pos == (pos_T *)-1)        /* jump to other file */
  6280.     {
  6281.         curwin->w_set_curswant = TRUE;
  6282.         check_cursor();
  6283.     }
  6284.     else if (pos != NULL)            /* can jump */
  6285.         nv_cursormark(cap, FALSE, pos);
  6286.     else
  6287.         clearopbeep(cap->oap);
  6288. # ifdef FEAT_FOLDING
  6289.     if (cap->oap->op_type == OP_NOP
  6290.         && (pos == (pos_T *)-1 || lnum != curwin->w_cursor.lnum)
  6291.         && (fdo_flags & FDO_MARK)
  6292.         && old_KeyTyped)
  6293.         foldOpenCursor();
  6294. # endif
  6295.     }
  6296. #else
  6297.     clearopbeep(cap->oap);
  6298. #endif
  6299. }
  6300.  
  6301. /*
  6302.  * Handle '"' command.
  6303.  */
  6304.     static void
  6305. nv_regname(cap)
  6306.     cmdarg_T    *cap;
  6307. {
  6308.     if (checkclearop(cap->oap))
  6309.     return;
  6310. #ifdef FEAT_EVAL
  6311.     if (cap->nchar == '=')
  6312.     cap->nchar = get_expr_register();
  6313. #endif
  6314.     if (cap->nchar != NUL && valid_yank_reg(cap->nchar, FALSE))
  6315.     {
  6316.     cap->oap->regname = cap->nchar;
  6317.     cap->opcount = cap->count0;    /* remember count before '"' */
  6318.     }
  6319.     else
  6320.     clearopbeep(cap->oap);
  6321. }
  6322.  
  6323. #ifdef FEAT_VISUAL
  6324. /*
  6325.  * Handle "v", "V" and "CTRL-V" commands.
  6326.  * Also for "gh", "gH" and "g^H" commands: Always start Select mode, cap->arg
  6327.  * is TRUE.
  6328.  */
  6329.     static void
  6330. nv_visual(cap)
  6331.     cmdarg_T    *cap;
  6332. {
  6333.     /* 'v', 'V' and CTRL-V can be used while an operator is pending to make it
  6334.      * characterwise, linewise, or blockwise. */
  6335.     if (cap->oap->op_type != OP_NOP)
  6336.     {
  6337.     cap->oap->motion_force = cap->cmdchar;
  6338.     finish_op = FALSE;    /* operator doesn't finish now but later */
  6339.     return;
  6340.     }
  6341.  
  6342.     /* Don't do anything when an operator is pending. */
  6343.     if (checkclearop(cap->oap))
  6344.     return;
  6345.  
  6346.     VIsual_select = cap->arg;
  6347.     if (VIsual_active)        /* change Visual mode */
  6348.     {
  6349.     if (VIsual_mode == cap->cmdchar)    /* stop visual mode */
  6350.         end_visual_mode();
  6351.     else                    /* toggle char/block mode */
  6352.     {                    /*       or char/line mode */
  6353.         VIsual_mode = cap->cmdchar;
  6354.         showmode();
  6355.     }
  6356.     redraw_curbuf_later(INVERTED);        /* update the inversion */
  6357.     }
  6358.     else            /* start Visual mode */
  6359.     {
  6360.     check_visual_highlight();
  6361.     if (cap->count0)            /* use previously selected part */
  6362.     {
  6363.         if (resel_VIsual_mode == NUL)   /* there is none */
  6364.         {
  6365.         beep_flush();
  6366.         return;
  6367.         }
  6368.         VIsual = curwin->w_cursor;
  6369.  
  6370.         VIsual_active = TRUE;
  6371.         VIsual_reselect = TRUE;
  6372.         if (!cap->arg)
  6373.         /* start Select mode when 'selectmode' contains "cmd" */
  6374.         may_start_select('c');
  6375. #ifdef FEAT_MOUSE
  6376.         setmouse();
  6377. #endif
  6378.         if (p_smd)
  6379.         redraw_cmdline = TRUE;        /* show visual mode later */
  6380.         /*
  6381.          * For V and ^V, we multiply the number of lines even if there
  6382.          * was only one -- webb
  6383.          */
  6384.         if (resel_VIsual_mode != 'v' || resel_VIsual_line_count > 1)
  6385.         {
  6386.         curwin->w_cursor.lnum +=
  6387.                     resel_VIsual_line_count * cap->count0 - 1;
  6388.         if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
  6389.             curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
  6390.         }
  6391.         VIsual_mode = resel_VIsual_mode;
  6392.         if (VIsual_mode == 'v')
  6393.         {
  6394.         if (resel_VIsual_line_count <= 1)
  6395.             curwin->w_cursor.col += resel_VIsual_col * cap->count0 - 1;
  6396.         else
  6397.             curwin->w_cursor.col = resel_VIsual_col;
  6398.         }
  6399.         if (resel_VIsual_col == MAXCOL)
  6400.         {
  6401.         curwin->w_curswant = MAXCOL;
  6402.         coladvance((colnr_T)MAXCOL);
  6403.         }
  6404.         else if (VIsual_mode == Ctrl_V)
  6405.         {
  6406.         validate_virtcol();
  6407.         curwin->w_curswant = curwin->w_virtcol
  6408.             + resel_VIsual_col * cap->count0 - 1;
  6409.         coladvance(curwin->w_curswant);
  6410.         }
  6411.         else
  6412.         curwin->w_set_curswant = TRUE;
  6413.         redraw_curbuf_later(INVERTED);    /* show the inversion */
  6414.     }
  6415.     else
  6416.     {
  6417.         if (!cap->arg)
  6418.         /* start Select mode when 'selectmode' contains "cmd" */
  6419.         may_start_select('c');
  6420.         n_start_visual_mode(cap->cmdchar);
  6421.     }
  6422.     }
  6423. }
  6424.  
  6425. /*
  6426.  * Start selection for Shift-movement keys.
  6427.  */
  6428.     void
  6429. start_selection()
  6430. {
  6431.     /* if 'selectmode' contains "key", start Select mode */
  6432.     may_start_select('k');
  6433.     n_start_visual_mode('v');
  6434. }
  6435.  
  6436. /*
  6437.  * Start Select mode, if "c" is in 'selectmode' and not in a mapping or menu.
  6438.  */
  6439.     void
  6440. may_start_select(c)
  6441.     int        c;
  6442. {
  6443.     VIsual_select = (stuff_empty() && typebuf_typed()
  6444.             && (vim_strchr(p_slm, c) != NULL));
  6445. }
  6446.  
  6447. /*
  6448.  * Start Visual mode "c".
  6449.  * Should set VIsual_select before calling this.
  6450.  */
  6451.     static void
  6452. n_start_visual_mode(c)
  6453.     int        c;
  6454. {
  6455.     VIsual_mode = c;
  6456.     VIsual_active = TRUE;
  6457.     VIsual_reselect = TRUE;
  6458. #ifdef FEAT_VIRTUALEDIT
  6459.     /* Corner case: the 0 position in a tab may change when going into
  6460.      * virtualedit.  Recalculate curwin->w_cursor to avoid bad hilighting.
  6461.      */
  6462.     if (c == Ctrl_V && (ve_flags & VE_BLOCK) && gchar_cursor() == TAB)
  6463.     coladvance(curwin->w_virtcol);
  6464. #endif
  6465.     VIsual = curwin->w_cursor;
  6466.  
  6467. #ifdef FEAT_FOLDING
  6468.     foldAdjustVisual();
  6469. #endif
  6470.  
  6471. #ifdef FEAT_MOUSE
  6472.     setmouse();
  6473. #endif
  6474.     if (p_smd)
  6475.     redraw_cmdline = TRUE;    /* show visual mode later */
  6476. #ifdef FEAT_CLIPBOARD
  6477.     /* Make sure the clipboard gets updated.  Needed because start and
  6478.      * end may still be the same, and the selection needs to be owned */
  6479.     clip_star.vmode = NUL;
  6480. #endif
  6481.  
  6482.     /* Only need to redraw this line. */
  6483.     curwin->w_old_cursor_lnum = curwin->w_cursor.lnum;
  6484.     curwin->w_old_visual_lnum = curwin->w_cursor.lnum;
  6485. }
  6486.  
  6487. #endif /* FEAT_VISUAL */
  6488.  
  6489. /*
  6490.  * CTRL-W: Window commands
  6491.  */
  6492.     static void
  6493. nv_window(cap)
  6494.     cmdarg_T    *cap;
  6495. {
  6496. #ifdef FEAT_WINDOWS
  6497.     if (!checkclearop(cap->oap))
  6498.     do_window(cap->nchar, cap->count0);    /* everything is in window.c */
  6499. #else
  6500.     (void)checkclearop(cap->oap);
  6501. #endif
  6502. }
  6503.  
  6504. /*
  6505.  * CTRL-Z: Suspend
  6506.  */
  6507.     static void
  6508. nv_suspend(cap)
  6509.     cmdarg_T    *cap;
  6510. {
  6511.     clearop(cap->oap);
  6512. #ifdef FEAT_VISUAL
  6513.     if (VIsual_active)
  6514.     end_visual_mode();        /* stop Visual mode */
  6515. #endif
  6516.     do_cmdline_cmd((char_u *)"st");
  6517. }
  6518.  
  6519. /*
  6520.  * Commands starting with "g".
  6521.  */
  6522.     static void
  6523. nv_g_cmd(cap)
  6524.     cmdarg_T    *cap;
  6525. {
  6526.     oparg_T    *oap = cap->oap;
  6527. #ifdef FEAT_VISUAL
  6528.     pos_T    tpos;
  6529. #endif
  6530. #ifdef FEAT_VIRTUALEDIT
  6531.     int        coladd;
  6532. #endif
  6533.     int        i;
  6534.     int        flag = FALSE;
  6535.  
  6536.     switch (cap->nchar)
  6537.     {
  6538. #ifdef MEM_PROFILE
  6539.     /*
  6540.      * "g^A": dump log of used memory.
  6541.      */
  6542.     case Ctrl_A:
  6543.     vim_mem_profile_dump();
  6544.     break;
  6545. #endif
  6546.  
  6547. #ifdef FEAT_VREPLACE
  6548.     /*
  6549.      * "gR": Enter virtual replace mode.
  6550.      */
  6551.     case 'R':
  6552.     cap->arg = TRUE;
  6553.     nv_Replace(cap);
  6554.     break;
  6555.  
  6556.     case 'r':
  6557.     nv_vreplace(cap);
  6558.     break;
  6559. #endif
  6560.  
  6561.     case '&':
  6562.     do_cmdline_cmd((char_u *)"%s//~/&");
  6563.     break;
  6564.  
  6565. #ifdef FEAT_VISUAL
  6566.     /*
  6567.      * "gv": Reselect the previous Visual area.  If Visual already active,
  6568.      *         exchange previous and current Visual area.
  6569.      */
  6570.     case 'v':
  6571.     if (checkclearop(oap))
  6572.         break;
  6573.  
  6574.     if (       curbuf->b_visual_start.lnum == 0
  6575.         || curbuf->b_visual_start.lnum > curbuf->b_ml.ml_line_count
  6576.         || curbuf->b_visual_end.lnum == 0)
  6577.         beep_flush();
  6578.     else
  6579.     {
  6580.         /* set w_cursor to the start of the Visual area, tpos to the end */
  6581.         if (VIsual_active)
  6582.         {
  6583.         i = VIsual_mode;
  6584.         VIsual_mode = curbuf->b_visual_mode;
  6585.         curbuf->b_visual_mode = i;
  6586.         i = curwin->w_curswant;
  6587.         curwin->w_curswant = curbuf->b_visual_curswant;
  6588.         curbuf->b_visual_curswant = i;
  6589.  
  6590.         tpos = curbuf->b_visual_end;
  6591.         curbuf->b_visual_end = curwin->w_cursor;
  6592.         curwin->w_cursor = curbuf->b_visual_start;
  6593.         curbuf->b_visual_start = VIsual;
  6594.  
  6595. #ifdef FEAT_VIRTUALEDIT
  6596.         coladd = tpos.coladd;
  6597. #endif
  6598.         }
  6599.         else
  6600.         {
  6601.         VIsual_mode = curbuf->b_visual_mode;
  6602.         curwin->w_curswant = curbuf->b_visual_curswant;
  6603.         tpos = curbuf->b_visual_end;
  6604.         curwin->w_cursor = curbuf->b_visual_start;
  6605. #ifdef FEAT_VIRTUALEDIT
  6606.         coladd = curbuf->b_visual_end.coladd;
  6607. #endif
  6608.         }
  6609.  
  6610.         VIsual_active = TRUE;
  6611.         VIsual_reselect = TRUE;
  6612.  
  6613.         /* Set Visual to the start and w_cursor to the end of the Visual
  6614.          * area.  Make sure they are on an existing character. */
  6615.         check_cursor();
  6616.         VIsual = curwin->w_cursor;
  6617.         curwin->w_cursor = tpos;
  6618. #ifdef FEAT_VIRTUALEDIT
  6619.         curwin->w_cursor.coladd = coladd;
  6620. #endif
  6621.         check_cursor();
  6622.         update_topline();
  6623.         /*
  6624.          * When called from normal "g" command: start Select mode when
  6625.          * 'selectmode' contains "cmd".  When called for K_SELECT, always
  6626.          * start Select mode.
  6627.          */
  6628.         if (cap->arg)
  6629.         VIsual_select = TRUE;
  6630.         else
  6631.         may_start_select('c');
  6632. #ifdef FEAT_MOUSE
  6633.         setmouse();
  6634. #endif
  6635. #ifdef FEAT_CLIPBOARD
  6636.         /* Make sure the clipboard gets updated.  Needed because start and
  6637.          * end are still the same, and the selection needs to be owned */
  6638.         clip_star.vmode = NUL;
  6639. #endif
  6640.         redraw_curbuf_later(INVERTED);
  6641.         showmode();
  6642.     }
  6643.     break;
  6644.     /*
  6645.      * "gV": Don't reselect the previous Visual area after a Select mode
  6646.      *         mapping of menu.
  6647.      */
  6648.     case 'V':
  6649.     VIsual_reselect = FALSE;
  6650.     break;
  6651.  
  6652.     /*
  6653.      * "gh":  start Select mode.
  6654.      * "gH":  start Select line mode.
  6655.      * "g^H": start Select block mode.
  6656.      */
  6657.     case K_BS:
  6658.     cap->nchar = Ctrl_H;
  6659.     /* FALLTHROUGH */
  6660.     case 'h':
  6661.     case 'H':
  6662.     case Ctrl_H:
  6663. # ifdef EBCDIC
  6664.     /* EBCDIC: 'v'-'h' != '^v'-'^h' */
  6665.     if (cap->nchar == Ctrl_H)
  6666.         cap->cmdchar = Ctrl_V;
  6667.     else
  6668. # endif
  6669.     cap->cmdchar = cap->nchar + ('v' - 'h');
  6670.     cap->arg = TRUE;
  6671.     nv_visual(cap);
  6672.     break;
  6673. #endif /* FEAT_VISUAL */
  6674.  
  6675.     /*
  6676.      * "gj" and "gk" two new funny movement keys -- up and down
  6677.      * movement based on *screen* line rather than *file* line.
  6678.      */
  6679.     case 'j':
  6680.     case K_DOWN:
  6681.     /* with 'nowrap' it works just like the normal "j" command */
  6682.     if (!curwin->w_p_wrap)
  6683.     {
  6684.         oap->motion_type = MLINE;
  6685.         i = cursor_down(cap->count1, oap->op_type == OP_NOP);
  6686.     }
  6687.     else
  6688.         i = nv_screengo(oap, FORWARD, cap->count1);
  6689.     if (i == FAIL)
  6690.         clearopbeep(oap);
  6691.     break;
  6692.  
  6693.     case 'k':
  6694.     case K_UP:
  6695.     /* with 'nowrap' it works just like the normal "k" command */
  6696.     if (!curwin->w_p_wrap)
  6697.     {
  6698.         oap->motion_type = MLINE;
  6699.         i = cursor_up(cap->count1, oap->op_type == OP_NOP);
  6700.     }
  6701.     else
  6702.         i = nv_screengo(oap, BACKWARD, cap->count1);
  6703.     if (i == FAIL)
  6704.         clearopbeep(oap);
  6705.     break;
  6706.  
  6707.     /*
  6708.      * "gJ": join two lines without inserting a space.
  6709.      */
  6710.     case 'J':
  6711.     nv_join(cap);
  6712.     break;
  6713.  
  6714.     /*
  6715.      * "g0", "g^" and "g$": Like "0", "^" and "$" but for screen lines.
  6716.      * "gm": middle of "g0" and "g$".
  6717.      */
  6718.     case '^':
  6719.     flag = TRUE;
  6720.     /* FALLTHROUGH */
  6721.  
  6722.     case '0':
  6723.     case 'm':
  6724.     case K_HOME:
  6725.     case K_KHOME:
  6726.     case K_XHOME:
  6727.     oap->motion_type = MCHAR;
  6728.     oap->inclusive = FALSE;
  6729.     if (curwin->w_p_wrap
  6730. #ifdef FEAT_VERTSPLIT
  6731.         && curwin->w_width != 0
  6732. #endif
  6733.         )
  6734.     {
  6735.         int        width1 = W_WIDTH(curwin) - curwin_col_off();
  6736.         int        width2 = width1 + curwin_col_off2();
  6737.  
  6738.         validate_virtcol();
  6739.         i = 0;
  6740.         if (curwin->w_virtcol >= (colnr_T)width1 && width2 > 0)
  6741.         i = (curwin->w_virtcol - width1) / width2 * width2 + width1;
  6742.     }
  6743.     else
  6744.         i = curwin->w_leftcol;
  6745.     /* Go to the middle of the screen line.  When 'number' is on and lines
  6746.      * are wrapping the middle can be more to the left.*/
  6747.     if (cap->nchar == 'm')
  6748.         i += (W_WIDTH(curwin) - curwin_col_off()
  6749.             + ((curwin->w_p_wrap && i > 0)
  6750.             ? curwin_col_off2() : 0)) / 2;
  6751.     coladvance((colnr_T)i);
  6752.     if (flag)
  6753.     {
  6754.         do
  6755.         i = gchar_cursor();
  6756.         while (vim_iswhite(i) && oneright() == OK);
  6757.     }
  6758.     curwin->w_set_curswant = TRUE;
  6759.     break;
  6760.  
  6761.     case '_':
  6762.     cap->oap->motion_type = MCHAR;
  6763.     cap->oap->inclusive = TRUE;
  6764.     curwin->w_curswant = MAXCOL;
  6765.     if (cursor_down((long)(cap->count1 - 1),
  6766.                      cap->oap->op_type == OP_NOP) == FAIL)
  6767.         clearopbeep(cap->oap);
  6768.     else
  6769.     {
  6770.         char_u  *ptr = ml_get_curline();
  6771.  
  6772.         while (curwin->w_cursor.col > 0
  6773.                     && vim_iswhite(ptr[curwin->w_cursor.col]))
  6774.         --curwin->w_cursor.col;
  6775.         curwin->w_set_curswant = TRUE;
  6776.     }
  6777.     break;
  6778.  
  6779.     case '$':
  6780.     case K_END:
  6781.     case K_KEND:
  6782.     case K_XEND:
  6783.     {
  6784.         int col_off = curwin_col_off();
  6785.  
  6786.         oap->motion_type = MCHAR;
  6787.         oap->inclusive = TRUE;
  6788.         if (curwin->w_p_wrap
  6789. #ifdef FEAT_VERTSPLIT
  6790.             && curwin->w_width != 0
  6791. #endif
  6792.            )
  6793.         {
  6794.         curwin->w_curswant = MAXCOL;    /* so we stay at the end */
  6795.         if (cap->count1 == 1)
  6796.         {
  6797.             int        width1 = W_WIDTH(curwin) - col_off;
  6798.             int        width2 = width1 + curwin_col_off2();
  6799.  
  6800.             validate_virtcol();
  6801.             i = width1 - 1;
  6802.             if (curwin->w_virtcol >= (colnr_T)width1)
  6803.             i += ((curwin->w_virtcol - width1) / width2 + 1)
  6804.                                      * width2;
  6805.             coladvance((colnr_T)i);
  6806. #if defined(FEAT_LINEBREAK) || defined(FEAT_MBYTE)
  6807.             if (curwin->w_cursor.col > 0 && curwin->w_p_wrap)
  6808.             {
  6809.             /*
  6810.              * Check for landing on a character that got split at
  6811.              * the end of the line.  We do not want to advance to
  6812.              * the next screen line.
  6813.              */
  6814.             validate_virtcol();
  6815.             if (curwin->w_virtcol > (colnr_T)i)
  6816.                 --curwin->w_cursor.col;
  6817.             }
  6818. #endif
  6819.         }
  6820.         else if (nv_screengo(oap, FORWARD, cap->count1 - 1) == FAIL)
  6821.             clearopbeep(oap);
  6822.         }
  6823.         else
  6824.         {
  6825.         i = curwin->w_leftcol + W_WIDTH(curwin) - col_off - 1;
  6826.         coladvance((colnr_T)i);
  6827.         curwin->w_set_curswant = TRUE;
  6828.         }
  6829.     }
  6830.     break;
  6831.  
  6832.     /*
  6833.      * "g*" and "g#", like "*" and "#" but without using "\<" and "\>"
  6834.      */
  6835.     case '*':
  6836.     case '#':
  6837. #if POUND != '#'
  6838.     case POUND:        /* pound sign (sometimes equal to '#') */
  6839. #endif
  6840.     case Ctrl_RSB:        /* :tag or :tselect for current identifier */
  6841.     case ']':            /* :tselect for current identifier */
  6842.     nv_ident(cap);
  6843.     break;
  6844.  
  6845.     /*
  6846.      * ge and gE: go back to end of word
  6847.      */
  6848.     case 'e':
  6849.     case 'E':
  6850.     oap->motion_type = MCHAR;
  6851.     curwin->w_set_curswant = TRUE;
  6852.     oap->inclusive = TRUE;
  6853.     if (bckend_word(cap->count1, cap->nchar == 'E', FALSE) == FAIL)
  6854.         clearopbeep(oap);
  6855.     break;
  6856.  
  6857.     /*
  6858.      * "g CTRL-G": display info about cursor position
  6859.      */
  6860.     case Ctrl_G:
  6861.     cursor_pos_info();
  6862.     break;
  6863.  
  6864.     /*
  6865.      * "gi": start Insert at the last position.
  6866.      */
  6867.     case 'i':
  6868.     if (curbuf->b_last_insert.lnum != 0)
  6869.     {
  6870.         curwin->w_cursor = curbuf->b_last_insert;
  6871.         check_cursor_lnum();
  6872.         i = (int)STRLEN(ml_get_curline());
  6873.         if (curwin->w_cursor.col > (colnr_T)i)
  6874.         {
  6875. #ifdef FEAT_VIRTUALEDIT
  6876.         if (virtual_active())
  6877.             curwin->w_cursor.coladd += curwin->w_cursor.col - i;
  6878. #endif
  6879.         curwin->w_cursor.col = i;
  6880.         }
  6881.     }
  6882.     cap->cmdchar = 'i';
  6883.     nv_edit(cap);
  6884.     break;
  6885.  
  6886.     /*
  6887.      * "gI": Start insert in column 1.
  6888.      */
  6889.     case 'I':
  6890.     beginline(0);
  6891.     if (!checkclearopq(oap))
  6892.     {
  6893.         /* This is a new edit command, not a restart.  We don't edit
  6894.          * recursively. */
  6895.         restart_edit = 0;
  6896.         if (edit('g', FALSE, cap->count1))
  6897.         cap->retval |= CA_COMMAND_BUSY;
  6898.     }
  6899.     break;
  6900.  
  6901. #ifdef FEAT_SEARCHPATH
  6902.     /*
  6903.      * "gf": goto file, edit file under cursor
  6904.      * "]f" and "[f": can also be used.
  6905.      */
  6906.     case 'f':
  6907.     nv_gotofile(cap);
  6908.     break;
  6909. #endif
  6910.  
  6911.     /* "g'm" and "g`m": jump to mark without setting pcmark */
  6912.     case '\'':
  6913.     cap->arg = TRUE;
  6914.     /*FALLTHROUGH*/
  6915.     case '`':
  6916.     nv_gomark(cap);
  6917.     break;
  6918.  
  6919.     /*
  6920.      * "gs": Goto sleep.
  6921.      */
  6922.     case 's':
  6923.     do_sleep(cap->count1 * 1000L);
  6924.     break;
  6925.  
  6926.     /*
  6927.      * "ga": Display the ascii value of the character under the
  6928.      * cursor.    It is displayed in decimal, hex, and octal. -- webb
  6929.      */
  6930.     case 'a':
  6931.     do_ascii(NULL);
  6932.     break;
  6933.  
  6934. #ifdef FEAT_MBYTE
  6935.     /*
  6936.      * "g8": Display the bytes used for the UTF-8 character under the
  6937.      * cursor.    It is displayed in hex.
  6938.      */
  6939.     case '8':
  6940.     show_utf8();
  6941.     break;
  6942. #endif
  6943.  
  6944.     /*
  6945.      * "gg": Goto the first line in file.  With a count it goes to
  6946.      * that line number like for "G". -- webb
  6947.      */
  6948.     case 'g':
  6949.     cap->arg = FALSE;
  6950.     nv_goto(cap);
  6951.     break;
  6952.  
  6953.     /*
  6954.      *     Two-character operators:
  6955.      *     "gq"        Format text
  6956.      *     "g~"        Toggle the case of the text.
  6957.      *     "gu"        Change text to lower case.
  6958.      *     "gU"        Change text to upper case.
  6959.      *   "g?"        rot13 encoding
  6960.      */
  6961.     case 'q':
  6962.     case '~':
  6963.     case 'u':
  6964.     case 'U':
  6965.     case '?':
  6966.     nv_operator(cap);
  6967.     break;
  6968.  
  6969.     /*
  6970.      * "gd": Find first occurence of pattern under the cursor in the
  6971.      *     current function
  6972.      * "gD": idem, but in the current file.
  6973.      */
  6974.     case 'd':
  6975.     case 'D':
  6976.     nv_gd(oap, cap->nchar);
  6977.     break;
  6978.  
  6979. #ifdef FEAT_MOUSE
  6980.     /*
  6981.      * g<*Mouse> : <C-*mouse>
  6982.      */
  6983.     case K_MIDDLEMOUSE:
  6984.     case K_MIDDLEDRAG:
  6985.     case K_MIDDLERELEASE:
  6986.     case K_LEFTMOUSE:
  6987.     case K_LEFTDRAG:
  6988.     case K_LEFTRELEASE:
  6989.     case K_RIGHTMOUSE:
  6990.     case K_RIGHTDRAG:
  6991.     case K_RIGHTRELEASE:
  6992.     mod_mask = MOD_MASK_CTRL;
  6993.     (void)do_mouse(oap, cap->nchar, BACKWARD, cap->count1, 0);
  6994.     break;
  6995. #endif
  6996.  
  6997.     case K_IGNORE:
  6998.     break;
  6999.  
  7000.     /*
  7001.      * "gP" and "gp": same as "P" and "p" but leave cursor just after new text
  7002.      */
  7003.     case 'p':
  7004.     case 'P':
  7005.     nv_put(cap);
  7006.     break;
  7007.  
  7008. #ifdef FEAT_BYTEOFF
  7009.     /* "go": goto byte count from start of buffer */
  7010.     case 'o':
  7011.     goto_byte(cap->count0);
  7012.     break;
  7013. #endif
  7014.  
  7015.     /* "gQ": improved Ex mode */
  7016.     case 'Q':
  7017. #ifdef FEAT_CMDWIN
  7018.     if (cmdwin_type != 0)
  7019.     {
  7020.         clearopbeep(cap->oap);
  7021.         break;
  7022.     }
  7023. #endif
  7024.     if (!checkclearopq(oap))
  7025.         do_exmode(TRUE);
  7026.     break;
  7027.  
  7028.     default:
  7029.     clearopbeep(oap);
  7030.     break;
  7031.     }
  7032. }
  7033.  
  7034. /*
  7035.  * Handle "o" and "O" commands.
  7036.  */
  7037.     static void
  7038. n_opencmd(cap)
  7039.     cmdarg_T    *cap;
  7040. {
  7041.     if (!checkclearopq(cap->oap))
  7042.     {
  7043. #ifdef FEAT_FOLDING
  7044.     if (cap->cmdchar == 'O')
  7045.         /* Open above the first line of a folded sequence of lines */
  7046.         (void)hasFolding(curwin->w_cursor.lnum,
  7047.                         &curwin->w_cursor.lnum, NULL);
  7048.     else
  7049.         /* Open below the last line of a folded sequence of lines */
  7050.         (void)hasFolding(curwin->w_cursor.lnum,
  7051.                         NULL, &curwin->w_cursor.lnum);
  7052. #endif
  7053.     if (u_save((linenr_T)(curwin->w_cursor.lnum -
  7054.                            (cap->cmdchar == 'O' ? 1 : 0)),
  7055.            (linenr_T)(curwin->w_cursor.lnum +
  7056.                            (cap->cmdchar == 'o' ? 1 : 0))
  7057.                ) == OK
  7058.         && open_line(cap->cmdchar == 'O' ? BACKWARD : FORWARD,
  7059. #ifdef FEAT_COMMENTS
  7060.             has_format_option(FO_OPEN_COMS) ? OPENLINE_DO_COM :
  7061. #endif
  7062.             0, 0))
  7063.     {
  7064.         /* This is a new edit command, not a restart.  We don't edit
  7065.          * recursively. */
  7066.         restart_edit = 0;
  7067.         if (edit(cap->cmdchar, TRUE, cap->count1))
  7068.         cap->retval |= CA_COMMAND_BUSY;
  7069.     }
  7070.     }
  7071. }
  7072.  
  7073. /*
  7074.  * "." command: redo last change.
  7075.  */
  7076.     static void
  7077. nv_dot(cap)
  7078.     cmdarg_T    *cap;
  7079. {
  7080.     if (!checkclearopq(cap->oap))
  7081.     {
  7082.     /*
  7083.      * if restart_edit is TRUE, the last but one command is repeated
  7084.      * instead of the last command (inserting text). This is used for
  7085.      * CTRL-O <.> in insert mode
  7086.      */
  7087.     if (start_redo(cap->count0, restart_edit != 0 && !arrow_used) == FAIL)
  7088.         clearopbeep(cap->oap);
  7089.     }
  7090. }
  7091.  
  7092. /*
  7093.  * CTRL-R: undo undo
  7094.  */
  7095.     static void
  7096. nv_redo(cap)
  7097.     cmdarg_T    *cap;
  7098. {
  7099.     if (!checkclearopq(cap->oap))
  7100.     {
  7101.     u_redo((int)cap->count1);
  7102.     curwin->w_set_curswant = TRUE;
  7103.     }
  7104. }
  7105.  
  7106. /*
  7107.  * Handle "U" command.
  7108.  */
  7109.     static void
  7110. nv_Undo(cap)
  7111.     cmdarg_T    *cap;
  7112. {
  7113.     /* In Visual mode and typing "gUU" triggers an operator */
  7114.     if (cap->oap->op_type == OP_UPPER
  7115. #ifdef FEAT_VISUAL
  7116.         || VIsual_active
  7117. #endif
  7118.         )
  7119.     {
  7120.     /* translate "gUU" to "gUgU" */
  7121.     cap->cmdchar = 'g';
  7122.     cap->nchar = 'U';
  7123.     nv_operator(cap);
  7124.     }
  7125.     else if (!checkclearopq(cap->oap))
  7126.     {
  7127.     u_undoline();
  7128.     curwin->w_set_curswant = TRUE;
  7129.     }
  7130. }
  7131.  
  7132. /*
  7133.  * '~' command: If tilde is not an operator and Visual is off: swap case of a
  7134.  * single character.
  7135.  */
  7136.     static void
  7137. nv_tilde(cap)
  7138.     cmdarg_T    *cap;
  7139. {
  7140.     if (!p_to
  7141. #ifdef FEAT_VISUAL
  7142.         && !VIsual_active
  7143. #endif
  7144.         && cap->oap->op_type != OP_TILDE)
  7145.     n_swapchar(cap);
  7146.     else
  7147.     nv_operator(cap);
  7148. }
  7149.  
  7150. /*
  7151.  * Handle an operator command.
  7152.  */
  7153.     static void
  7154. nv_operator(cap)
  7155.     cmdarg_T    *cap;
  7156. {
  7157.     int        op_type;
  7158.  
  7159.     op_type = get_op_type(cap->cmdchar, cap->nchar);
  7160.  
  7161.     if (op_type == cap->oap->op_type)        /* double operator works on lines */
  7162.     nv_lineop(cap);
  7163.     else if (!checkclearop(cap->oap))
  7164.     {
  7165.     cap->oap->start = curwin->w_cursor;
  7166.     cap->oap->op_type = op_type;
  7167.     }
  7168. }
  7169.  
  7170. /*
  7171.  * Handle linewise operator "dd", "yy", etc.
  7172.  *
  7173.  * "_" is is a strange motion command that helps make operators more logical.
  7174.  * It is actually implemented, but not documented in the real Vi.  This motion
  7175.  * command actually refers to "the current line".  Commands like "dd" and "yy"
  7176.  * are really an alternate form of "d_" and "y_".  It does accept a count, so
  7177.  * "d3_" works to delete 3 lines.
  7178.  */
  7179.     static void
  7180. nv_lineop(cap)
  7181.     cmdarg_T    *cap;
  7182. {
  7183.     cap->oap->motion_type = MLINE;
  7184.     if (cursor_down(cap->count1 - 1L, cap->oap->op_type == OP_NOP) == FAIL)
  7185.     clearopbeep(cap->oap);
  7186.     else if (  cap->oap->op_type == OP_DELETE
  7187.         || cap->oap->op_type == OP_LSHIFT
  7188.         || cap->oap->op_type == OP_RSHIFT)
  7189.     beginline(BL_SOL | BL_FIX);
  7190.     else if (cap->oap->op_type != OP_YANK)    /* 'Y' does not move cursor */
  7191.     beginline(BL_WHITE | BL_FIX);
  7192. }
  7193.  
  7194. /*
  7195.  * <Home> command.
  7196.  */
  7197.     static void
  7198. nv_home(cap)
  7199.     cmdarg_T    *cap;
  7200. {
  7201.     cap->count0 = 1;
  7202.     nv_pipe(cap);
  7203. }
  7204.  
  7205. /*
  7206.  * "|" command.
  7207.  */
  7208.     static void
  7209. nv_pipe(cap)
  7210.     cmdarg_T *cap;
  7211. {
  7212.     cap->oap->motion_type = MCHAR;
  7213.     cap->oap->inclusive = FALSE;
  7214.     beginline(0);
  7215.     if (cap->count0 > 0)
  7216.     {
  7217.     coladvance((colnr_T)(cap->count0 - 1));
  7218.     curwin->w_curswant = (colnr_T)(cap->count0 - 1);
  7219.     }
  7220.     else
  7221.     curwin->w_curswant = 0;
  7222.     /* keep curswant at the column where we wanted to go, not where
  7223.        we ended; differs is line is too short */
  7224.     curwin->w_set_curswant = FALSE;
  7225. }
  7226.  
  7227. /*
  7228.  * Handle back-word command "b" and "B".
  7229.  * cap->arg is 1 for "B"
  7230.  */
  7231.     static void
  7232. nv_bck_word(cap)
  7233.     cmdarg_T    *cap;
  7234. {
  7235.     cap->oap->motion_type = MCHAR;
  7236.     cap->oap->inclusive = FALSE;
  7237.     curwin->w_set_curswant = TRUE;
  7238.     if (bck_word(cap->count1, cap->arg, FALSE) == FAIL)
  7239.     clearopbeep(cap->oap);
  7240. #ifdef FEAT_FOLDING
  7241.     else if ((fdo_flags & FDO_HOR) && KeyTyped && cap->oap->op_type == OP_NOP)
  7242.     foldOpenCursor();
  7243. #endif
  7244. }
  7245.  
  7246. /*
  7247.  * Handle word motion commands "e", "E", "w" and "W".
  7248.  * cap->arg is TRUE for "E" and "W".
  7249.  */
  7250.     static void
  7251. nv_wordcmd(cap)
  7252.     cmdarg_T    *cap;
  7253. {
  7254.     int        n;
  7255.     int        word_end;
  7256.     int        flag = FALSE;
  7257.  
  7258.     /*
  7259.      * Set inclusive for the "E" and "e" command.
  7260.      */
  7261.     if (cap->cmdchar == 'e' || cap->cmdchar == 'E')
  7262.     word_end = TRUE;
  7263.     else
  7264.     word_end = FALSE;
  7265.     cap->oap->inclusive = word_end;
  7266.  
  7267.     /*
  7268.      * "cw" and "cW" are a special case.
  7269.      */
  7270.     if (!word_end && cap->oap->op_type == OP_CHANGE)
  7271.     {
  7272.     n = gchar_cursor();
  7273.     if (n != NUL)            /* not an empty line */
  7274.     {
  7275.         if (vim_iswhite(n))
  7276.         {
  7277.         /*
  7278.          * Reproduce a funny Vi behaviour: "cw" on a blank only
  7279.          * changes one character, not all blanks until the start of
  7280.          * the next word.  Only do this when the 'w' flag is included
  7281.          * in 'cpoptions'.
  7282.          */
  7283.         if (cap->count1 == 1 && vim_strchr(p_cpo, CPO_CW) != NULL)
  7284.         {
  7285.             cap->oap->inclusive = TRUE;
  7286.             cap->oap->motion_type = MCHAR;
  7287.             return;
  7288.         }
  7289.         }
  7290.         else
  7291.         {
  7292.         /*
  7293.          * This is a little strange. To match what the real Vi does,
  7294.          * we effectively map 'cw' to 'ce', and 'cW' to 'cE', provided
  7295.          * that we are not on a space or a TAB.  This seems impolite
  7296.          * at first, but it's really more what we mean when we say
  7297.          * 'cw'.
  7298.          * Another strangeness: When standing on the end of a word
  7299.          * "ce" will change until the end of the next wordt, but "cw"
  7300.          * will change only one character! This is done by setting
  7301.          * flag.
  7302.          */
  7303.         cap->oap->inclusive = TRUE;
  7304.         word_end = TRUE;
  7305.         flag = TRUE;
  7306.         }
  7307.     }
  7308.     }
  7309.  
  7310.     cap->oap->motion_type = MCHAR;
  7311.     curwin->w_set_curswant = TRUE;
  7312.     if (word_end)
  7313.     n = end_word(cap->count1, cap->arg, flag, FALSE);
  7314.     else
  7315.     n = fwd_word(cap->count1, cap->arg, cap->oap->op_type != OP_NOP);
  7316.  
  7317.     /* Don't leave the cursor on the NUL past a line */
  7318.     if (curwin->w_cursor.col && gchar_cursor() == NUL)
  7319.     {
  7320.     --curwin->w_cursor.col;
  7321.     cap->oap->inclusive = TRUE;
  7322.     }
  7323.  
  7324.     if (n == FAIL && cap->oap->op_type == OP_NOP)
  7325.     clearopbeep(cap->oap);
  7326.     else
  7327.     {
  7328. #ifdef FEAT_VISUAL
  7329.     adjust_for_sel(cap);
  7330. #endif
  7331. #ifdef FEAT_FOLDING
  7332.     if ((fdo_flags & FDO_HOR) && KeyTyped && cap->oap->op_type == OP_NOP)
  7333.         foldOpenCursor();
  7334. #endif
  7335.     }
  7336. }
  7337.  
  7338. /*
  7339.  * "0" and "^" commands.
  7340.  * cap->arg is the argument for beginline().
  7341.  */
  7342.     static void
  7343. nv_beginline(cap)
  7344.     cmdarg_T    *cap;
  7345. {
  7346.     cap->oap->motion_type = MCHAR;
  7347.     cap->oap->inclusive = FALSE;
  7348.     beginline(cap->arg);
  7349. #ifdef FEAT_FOLDING
  7350.     if ((fdo_flags & FDO_HOR) && KeyTyped && cap->oap->op_type == OP_NOP)
  7351.     foldOpenCursor();
  7352. #endif
  7353. }
  7354.  
  7355. #ifdef FEAT_VISUAL
  7356. /*
  7357.  * In exclusive Visual mode, may include the last character.
  7358.  */
  7359.     static void
  7360. adjust_for_sel(cap)
  7361.     cmdarg_T    *cap;
  7362. {
  7363.     if (VIsual_active && cap->oap->inclusive && *p_sel == 'e'
  7364.         && gchar_cursor() != NUL && lt(VIsual, curwin->w_cursor))
  7365.     {
  7366. # ifdef FEAT_MBYTE
  7367.     if (has_mbyte)
  7368.         inc_cursor();
  7369.     else
  7370. # endif
  7371.         ++curwin->w_cursor.col;
  7372.     cap->oap->inclusive = FALSE;
  7373.     }
  7374. }
  7375.  
  7376. /*
  7377.  * Exclude last character at end of Visual area for 'selection' == "exclusive".
  7378.  * Should check VIsual_mode before calling this.
  7379.  * Returns TRUE when backed up to the previous line.
  7380.  */
  7381.     static int
  7382. unadjust_for_sel()
  7383. {
  7384.     pos_T    *pp;
  7385.  
  7386.     if (*p_sel == 'e' && !equal(VIsual, curwin->w_cursor))
  7387.     {
  7388.     if (lt(VIsual, curwin->w_cursor))
  7389.         pp = &curwin->w_cursor;
  7390.     else
  7391.         pp = &VIsual;
  7392.     if (pp->col > 0)
  7393.         --pp->col;
  7394.     else if (pp->lnum > 1)
  7395.     {
  7396.         --pp->lnum;
  7397.         pp->col = (colnr_T)STRLEN(ml_get(pp->lnum));
  7398.         return TRUE;
  7399.     }
  7400.     }
  7401.     return FALSE;
  7402. }
  7403.  
  7404. /*
  7405.  * SELECT key in Normal or Visual mode: end of Select mode mapping.
  7406.  */
  7407.     static void
  7408. nv_select(cap)
  7409.     cmdarg_T    *cap;
  7410. {
  7411.     if (VIsual_active)
  7412.     VIsual_select = TRUE;
  7413.     else if (VIsual_reselect)
  7414.     {
  7415.     cap->nchar = 'v';        /* fake "gv" command */
  7416.     cap->arg = TRUE;
  7417.     nv_g_cmd(cap);
  7418.     }
  7419. }
  7420.  
  7421. #endif
  7422.  
  7423. /*
  7424.  * "G", "gg", CTRL-END, CTRL-HOME.
  7425.  * cap->arg is TRUE for "G".
  7426.  */
  7427.     static void
  7428. nv_goto(cap)
  7429.     cmdarg_T    *cap;
  7430. {
  7431.     linenr_T    lnum;
  7432.  
  7433.     if (cap->arg)
  7434.     lnum = curbuf->b_ml.ml_line_count;
  7435.     else
  7436.     lnum = 1L;
  7437.     cap->oap->motion_type = MLINE;
  7438.     setpcmark();
  7439.  
  7440.     /* When a count is given, use it instead of the default lnum */
  7441.     if (cap->count0 != 0)
  7442.     lnum = cap->count0;
  7443.     if (lnum < 1L)
  7444.     lnum = 1L;
  7445.     else if (lnum > curbuf->b_ml.ml_line_count)
  7446.     lnum = curbuf->b_ml.ml_line_count;
  7447.     curwin->w_cursor.lnum = lnum;
  7448.     beginline(BL_SOL | BL_FIX);
  7449. #ifdef FEAT_FOLDING
  7450.     if ((fdo_flags & FDO_JUMP) && KeyTyped && cap->oap->op_type == OP_NOP)
  7451.     foldOpenCursor();
  7452. #endif
  7453. }
  7454.  
  7455. /*
  7456.  * CTRL-\ in Normal mode.
  7457.  */
  7458.     static void
  7459. nv_normal(cap)
  7460.     cmdarg_T    *cap;
  7461. {
  7462.     if (safe_vgetc() == Ctrl_N)
  7463.     {
  7464.     clearop(cap->oap);
  7465.     restart_edit = 0;
  7466. #ifdef FEAT_CMDWIN
  7467.     if (cmdwin_type != 0)
  7468.         cmdwin_result = Ctrl_C;
  7469. #endif
  7470. #ifdef FEAT_VISUAL
  7471.     if (VIsual_active)
  7472.     {
  7473.         end_visual_mode();        /* stop Visual */
  7474.         redraw_curbuf_later(INVERTED);
  7475.     }
  7476. #endif
  7477.     }
  7478.     else
  7479.     clearopbeep(cap->oap);
  7480. }
  7481.  
  7482. /*
  7483.  * ESC in Normal mode: beep, but don't flush buffers.
  7484.  * Don't even beep if we are canceling a command.
  7485.  */
  7486.     static void
  7487. nv_esc(cap)
  7488.     cmdarg_T    *cap;
  7489. {
  7490.     if (cap->arg)        /* TRUE for CTRL-C */
  7491.     {
  7492.     restart_edit = 0;
  7493. #ifdef FEAT_CMDWIN
  7494.     if (cmdwin_type != 0)
  7495.     {
  7496.         cmdwin_result = K_IGNORE;
  7497.         return;
  7498.     }
  7499. #endif
  7500.     }
  7501.  
  7502. #ifdef FEAT_VISUAL
  7503.     if (VIsual_active)
  7504.     {
  7505.     end_visual_mode();    /* stop Visual */
  7506.     check_cursor_col();    /* make sure cursor is not beyond EOL */
  7507.     curwin->w_set_curswant = TRUE;
  7508.     redraw_curbuf_later(INVERTED);
  7509.     }
  7510.     else
  7511. #endif
  7512.     if (cap->oap->op_type == OP_NOP
  7513.         && cap->opcount == 0
  7514.         && cap->count0 == 0
  7515.         && cap->oap->regname == 0
  7516.         && !p_im)
  7517.     vim_beep();
  7518.     clearop(cap->oap);
  7519.     if (restart_edit == 0 && goto_im())
  7520.     restart_edit = 'a';
  7521. }
  7522.  
  7523. /*
  7524.  * Handle "A", "a", "I", "i" and <Insert> commands.
  7525.  */
  7526.     static void
  7527. nv_edit(cap)
  7528.     cmdarg_T *cap;
  7529. {
  7530.     /* <Insert> is equal to "i" */
  7531.     if (cap->cmdchar == K_INS || cap->cmdchar == K_KINS)
  7532.     cap->cmdchar = 'i';
  7533.  
  7534. #ifdef FEAT_VISUAL
  7535.     /* in Visual mode "A" and "I" are an operator */
  7536.     if (VIsual_active && (cap->cmdchar == 'A' || cap->cmdchar == 'I'))
  7537.     v_visop(cap);
  7538.  
  7539.     /* in Visual mode and after an operator "a" and "i" are for text objects */
  7540.     else
  7541. #endif
  7542.     if ((cap->cmdchar == 'a' || cap->cmdchar == 'i')
  7543.         && (cap->oap->op_type != OP_NOP
  7544. #ifdef FEAT_VISUAL
  7545.         || VIsual_active
  7546. #endif
  7547.         ))
  7548.     {
  7549. #ifdef FEAT_TEXTOBJ
  7550.     nv_object(cap);
  7551. #else
  7552.     clearopbeep(cap->oap);
  7553. #endif
  7554.     }
  7555.     else if (!curbuf->b_p_ma && !p_im)
  7556.     {
  7557.     /* Only give this error when 'insertmode' is off. */
  7558.     EMSG(_(e_modifiable));
  7559.     clearop(cap->oap);
  7560.     }
  7561.     else if (!checkclearopq(cap->oap))
  7562.     {
  7563.     switch (cap->cmdchar)
  7564.     {
  7565.         case 'A':    /* "A"ppend after the line */
  7566.         curwin->w_set_curswant = TRUE;
  7567. #ifdef FEAT_VIRTUALEDIT
  7568.         if (ve_flags == VE_ALL)
  7569.         {
  7570.             int save_State = State;
  7571.  
  7572.             /* Pretent Insert mode here to allow the cursor on the
  7573.              * character past the end of the line */
  7574.             State = INSERT;
  7575.             coladvance((colnr_T)MAXCOL);
  7576.             State = save_State;
  7577.         }
  7578.         else
  7579. #endif
  7580.             curwin->w_cursor.col += (colnr_T)STRLEN(ml_get_cursor());
  7581.         break;
  7582.  
  7583.         case 'I':    /* "I"nsert before the first non-blank */
  7584.         beginline(BL_WHITE);
  7585.         break;
  7586.  
  7587.         case 'a':    /* "a"ppend is like "i"nsert on the next character. */
  7588. #ifdef FEAT_VIRTUALEDIT
  7589.         /* increment coladd when in virtual space, increment the
  7590.          * column otherwise, also to append after an unprintable char */
  7591.         if (virtual_active()
  7592.             && (curwin->w_cursor.coladd > 0
  7593.                 || *ml_get_cursor() == NUL
  7594.                 || *ml_get_cursor() == TAB))
  7595.             curwin->w_cursor.coladd++;
  7596.         else
  7597. #endif
  7598.         if (*ml_get_cursor() != NUL)
  7599.             inc_cursor();
  7600.         break;
  7601.     }
  7602.  
  7603. #ifdef FEAT_VIRTUALEDIT
  7604.     if (curwin->w_cursor.coladd && cap->cmdchar != 'A')
  7605.     {
  7606.         int save_State = State;
  7607.  
  7608.         /* Pretent Insert mode here to allow the cursor on the
  7609.          * character past the end of the line */
  7610.         State = INSERT;
  7611.         coladvance(getviscol());
  7612.         State = save_State;
  7613.     }
  7614. #endif
  7615.  
  7616.     /* This is a new edit command, not a restart.  We don't edit
  7617.      * recursively. */
  7618.     restart_edit = 0;
  7619.     if (edit(cap->cmdchar, FALSE, cap->count1))
  7620.         cap->retval |= CA_COMMAND_BUSY;
  7621.     }
  7622. }
  7623.  
  7624. #ifdef FEAT_TEXTOBJ
  7625. /*
  7626.  * "a" or "i" while an operator is pending or in Visual mode: object motion.
  7627.  */
  7628.     static void
  7629. nv_object(cap)
  7630.     cmdarg_T    *cap;
  7631. {
  7632.     int        flag;
  7633.     int        include;
  7634.     char_u    *mps_save;
  7635.  
  7636.     if (cap->cmdchar == 'i')
  7637.     include = FALSE;    /* "ix" = inner object: exclude white space */
  7638.     else
  7639.     include = TRUE;        /* "ax" = an object: include white space */
  7640.  
  7641.     /* Make sure (), [], {} and <> are in 'matchpairs' */
  7642.     mps_save = curbuf->b_p_mps;
  7643.     curbuf->b_p_mps = (char_u *)"(:),{:},[:],<:>";
  7644.  
  7645.     switch (cap->nchar)
  7646.     {
  7647.     case 'w': /* "aw" = a word */
  7648.         flag = current_word(cap->oap, cap->count1, include, FALSE);
  7649.         break;
  7650.     case 'W': /* "aW" = a WORD */
  7651.         flag = current_word(cap->oap, cap->count1, include, TRUE);
  7652.         break;
  7653.     case 'b': /* "ab" = a braces block */
  7654.     case '(':
  7655.     case ')':
  7656.         flag = current_block(cap->oap, cap->count1, include, '(', ')');
  7657.         break;
  7658.     case 'B': /* "aB" = a Brackets block */
  7659.     case '{':
  7660.     case '}':
  7661.         flag = current_block(cap->oap, cap->count1, include, '{', '}');
  7662.         break;
  7663.     case '[': /* "a[" = a [] block */
  7664.     case ']':
  7665.         flag = current_block(cap->oap, cap->count1, include, '[', ']');
  7666.         break;
  7667.     case '<': /* "a<" = a <> block */
  7668.     case '>':
  7669.         flag = current_block(cap->oap, cap->count1, include, '<', '>');
  7670.         break;
  7671.     case 'p': /* "ap" = a paragraph */
  7672.         flag = current_par(cap->oap, cap->count1, include, 'p');
  7673.         break;
  7674.     case 's': /* "as" = a sentence */
  7675.         flag = current_sent(cap->oap, cap->count1, include);
  7676.         break;
  7677. #if 0    /* TODO */
  7678.     case 'S': /* "aS" = a section */
  7679.     case 'f': /* "af" = a filename */
  7680.     case 'u': /* "au" = a URL */
  7681. #endif
  7682.     default:
  7683.         flag = FAIL;
  7684.         break;
  7685.     }
  7686.  
  7687.     curbuf->b_p_mps = mps_save;
  7688.     if (flag == FAIL)
  7689.     clearopbeep(cap->oap);
  7690.     adjust_cursor_col();
  7691.     curwin->w_set_curswant = TRUE;
  7692. }
  7693. #endif
  7694.  
  7695. /*
  7696.  * "q" command: Start/stop recording.
  7697.  * "q:", "q/", "q?": edit command-line in command-line window.
  7698.  */
  7699.     static void
  7700. nv_record(cap)
  7701.     cmdarg_T    *cap;
  7702. {
  7703.     if (cap->oap->op_type == OP_FORMAT)
  7704.     {
  7705.     /* "gqq" is the same as "gqgq": format line */
  7706.     cap->cmdchar = 'g';
  7707.     cap->nchar = 'q';
  7708.     nv_operator(cap);
  7709.     }
  7710.     else if (!checkclearop(cap->oap))
  7711.     {
  7712. #ifdef FEAT_CMDWIN
  7713.     if (cap->nchar == ':' || cap->nchar == '/' || cap->nchar == '?')
  7714.     {
  7715.         stuffcharReadbuff(cap->nchar);
  7716.         stuffcharReadbuff(K_CMDWIN);
  7717.     }
  7718.     else
  7719. #endif
  7720.         /* (stop) recording into a named register, unless executing a
  7721.          * register */
  7722.         if (!Exec_reg && do_record(cap->nchar) == FAIL)
  7723.         clearopbeep(cap->oap);
  7724.     }
  7725. }
  7726.  
  7727. /*
  7728.  * Handle the "@r" command.
  7729.  */
  7730.     static void
  7731. nv_at(cap)
  7732.     cmdarg_T    *cap;
  7733. {
  7734.     if (checkclearop(cap->oap))
  7735.     return;
  7736. #ifdef FEAT_EVAL
  7737.     if (cap->nchar == '=')
  7738.     {
  7739.     if (get_expr_register() == NUL)
  7740.         return;
  7741.     }
  7742. #endif
  7743.     while (cap->count1-- && !got_int)
  7744.     {
  7745.     if (do_execreg(cap->nchar, FALSE, FALSE) == FAIL)
  7746.     {
  7747.         clearopbeep(cap->oap);
  7748.         break;
  7749.     }
  7750.     line_breakcheck();
  7751.     }
  7752. }
  7753.  
  7754. /*
  7755.  * Handle the CTRL-U and CTRL-D commands.
  7756.  */
  7757.     static void
  7758. nv_halfpage(cap)
  7759.     cmdarg_T    *cap;
  7760. {
  7761.     if ((cap->cmdchar == Ctrl_U && curwin->w_cursor.lnum == 1)
  7762.         || (cap->cmdchar == Ctrl_D
  7763.         && curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count))
  7764.     clearopbeep(cap->oap);
  7765.     else if (!checkclearop(cap->oap))
  7766.     halfpage(cap->cmdchar == Ctrl_D, cap->count0);
  7767. }
  7768.  
  7769. /*
  7770.  * Handle "J" or "gJ" command.
  7771.  */
  7772.     static void
  7773. nv_join(cap)
  7774.     cmdarg_T *cap;
  7775. {
  7776. #ifdef FEAT_VISUAL
  7777.     if (VIsual_active)    /* join the visual lines */
  7778.     nv_operator(cap);
  7779.     else
  7780. #endif
  7781.     if (!checkclearop(cap->oap))
  7782.     {
  7783.     if (cap->count0 <= 1)
  7784.         cap->count0 = 2;        /* default for join is two lines! */
  7785.     if (curwin->w_cursor.lnum + cap->count0 - 1 >
  7786.                            curbuf->b_ml.ml_line_count)
  7787.         clearopbeep(cap->oap);  /* beyond last line */
  7788.     else
  7789.     {
  7790.         prep_redo(cap->oap->regname, cap->count0,
  7791.              NUL, cap->cmdchar, NUL, NUL, cap->nchar);
  7792.         do_do_join(cap->count0, cap->nchar == NUL);
  7793.     }
  7794.     }
  7795. }
  7796.  
  7797. /*
  7798.  * "P", "gP", "p" and "gp" commands.
  7799.  */
  7800.     static void
  7801. nv_put(cap)
  7802.     cmdarg_T  *cap;
  7803. {
  7804. #ifdef FEAT_VISUAL
  7805.     pos_T    curpos;
  7806.     colnr_T    left, right;
  7807. #endif
  7808.     int        dir;
  7809.  
  7810.     if (cap->oap->op_type != OP_NOP)
  7811.     clearopbeep(cap->oap);
  7812.     else
  7813.     {
  7814. #ifdef FEAT_VISUAL
  7815.     if (VIsual_active)
  7816.     {
  7817.         /* Putting in Visual mode: The put text replaces the selected
  7818.          * text.  First put the register at the end of the Visual
  7819.          * selection, then delete the selected text. */
  7820.         curpos = curwin->w_cursor;
  7821.         if (VIsual_mode == Ctrl_V)
  7822.         {
  7823.         getvcols(curwin, &curwin->w_cursor, &VIsual, &left, &right);
  7824.         if (lt(VIsual, curwin->w_cursor))
  7825.             curwin->w_cursor = VIsual;
  7826.         coladvance(right);
  7827.         }
  7828.         else if (lt(curwin->w_cursor, VIsual))
  7829.         curwin->w_cursor = VIsual;
  7830.         if (VIsual_mode == 'v' && *p_sel == 'e')
  7831.         dir = BACKWARD;
  7832.         else
  7833.         dir = FORWARD;
  7834.     }
  7835.     else
  7836. #endif
  7837.         dir = (cap->cmdchar == 'P'
  7838.             || (cap->cmdchar == 'g' && cap->nchar == 'P'))
  7839.                              ? BACKWARD : FORWARD;
  7840.     prep_redo_cmd(cap);
  7841.     do_put(cap->oap->regname, dir,
  7842.               cap->count1, cap->cmdchar == 'g' ? PUT_CURSEND : 0);
  7843.  
  7844. #ifdef FEAT_VISUAL
  7845.     if (VIsual_active)
  7846.     {
  7847.         /* Now delete the selected text. */
  7848.         cap->cmdchar = 'd';
  7849.         cap->nchar = NUL;
  7850.         cap->oap->regname = NUL;
  7851.         curwin->w_cursor = curpos;
  7852.         nv_operator(cap);
  7853.     }
  7854. #endif
  7855.     }
  7856. }
  7857.  
  7858. /*
  7859.  * "o" and "O" commands.
  7860.  */
  7861.     static void
  7862. nv_open(cap)
  7863.     cmdarg_T    *cap;
  7864. {
  7865. #ifdef FEAT_VISUAL
  7866.     if (VIsual_active)  /* switch start and end of visual */
  7867.     v_swap_corners(cap->cmdchar);
  7868.     else
  7869. #endif
  7870.     n_opencmd(cap);
  7871. }
  7872.  
  7873. #ifdef FEAT_SNIFF
  7874. /*ARGSUSED*/
  7875.     static void
  7876. nv_sniff(cap)
  7877.     cmdarg_T    *cap;
  7878. {
  7879.     ProcessSniffRequests();
  7880. }
  7881. #endif
  7882.